Yanıtlar:
Çünkü sadece 1 cevap yok ...
shell
komut satırı genişletmexargs
özel araçwhile read
bazı sözlerlewhile read -u
etkileşimli işleme fd
için özel kullanarak (örnek)OP isteği ilgili olarak: çalışan chmod
dosyasında yer alan tüm hedeflere , xargs
belirtilen araçtır. Ancak diğer bazı uygulamalar için az miktarda dosya vb.
Dosyanız çok büyük değilse ve tüm dosyalar iyi adlandırılmışsa (boşluklar veya tırnak işaretleri gibi diğer özel karakterler olmadan), shell
komut satırı genişletmesini kullanabilirsiniz . basitçe:
chmod 755 $(<file.txt)
Az miktarda dosya (satır) için bu komut daha açıktır.
xargs
doğru araçDaha fazla sayıda dosya veya giriş dosyanızdaki neredeyse her sayıda satır için ...
Birçokları için binutils'ler araçları gibi chown
, chmod
, rm
, cp -t
...
xargs chmod 755 <file.txt
Özel karakterleriniz ve / veya çok fazla satırınız varsa file.txt
.
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
komutunuzun girişle tam olarak 1 kez çalıştırılması gerekiyorsa:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
Bu örnek için bu gerekli değildir, çünkü chmod
çoklu dosyaları bağımsız değişken olarak kabul et, ancak bu soru başlığıyla eşleşir.
Bazı özel durumlar için, oluşturulan komutlarda dosya bağımsız değişkeninin konumunu şu şekilde tanımlayabilirsiniz xargs
:
xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
seq 1 5
Giriş olarak test etBunu dene:
xargs -n 1 -I{} echo Blah {} blabla {}.. < <(seq 1 5)
Blah 1 blabla 1..
Blah 2 blabla 2..
Blah 3 blabla 3..
Blah 4 blabla 4..
Blah 5 blabla 5..
Komutanın her satıra bir kez yapıldığı yer .
while read
ve varyantlar.OP'nin önereceği gibi cat file.txt | while read in; do chmod 755 "$in"; done
, ancak 2 sorun var:
cat |
Bir olan gereksiz çatal ve
| while ... ;done
çevrenin sonradan kaybolacağı bir alt kabuk olacak ;done
.
Yani bu daha iyi yazılabilir:
while read in; do chmod 755 "$in"; done < file.txt
Fakat,
Hakkında uyarılabilir $IFS
ve read
işaretler alabilirsiniz:
help read
read: read [-r] ... [-d delim] ... [name ...] ... Reads a single line from the standard input... The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on... Only the characters found in $IFS are recognized as word delimiters. ... Options: ... -d delim continue until the first character of DELIM is read, rather than newline ... -r do not allow backslashes to escape any characters ... Exit Status: The return code is zero, unless end-of-file is encountered...
Bazı durumlarda,
while IFS= read -r in;do chmod 755 "$in";done <file.txt
Yabancı adlarla ilgili sorunlardan kaçınmak için. Ve belki de aşağıdakilerle ilgili problemleri çözerseniz UTF-8
:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txt
STDIN
Okuma için kullandığınız sırada file.txt
, komut dosyanız etkileşimli olamazdı ( STDIN
artık kullanamazsınız ).
while read -u
, özel kullanarak fd
.Söz dizimi: while read ...;done <file.txt
yönlendirir STDIN
için file.txt
. Bu, bitene kadar süreçle başa çıkamayacağınız anlamına gelir.
Etkileşimli bir araç oluşturmayı planlıyorsanız , STDIN
bazı alternatif dosya tanımlayıcıları kullanmaktan kaçınmanız ve kullanmanız gerekir .
Sabitler dosya tanımlayıcıları şunlardır: 0
için STDIN , 1
için STDOUT ve 2
için STDERR . Bunları şu şekilde görebilirsiniz:
ls -l /dev/fd/
veya
ls -l /proc/self/fd/
Oradan, dosya tanımlayıcı olarak 0
ve arasında 63
(ve aslında sysctl
süper kullanıcı aracına bağlı olarak ) arasında kullanılmayan numarayı seçmelisiniz :
Bu demo için fd kullanacağım 7
:
exec 7<file.txt # Without spaces between `7` and `<`!
ls -l /dev/fd/
Sonra şu şekilde kullanabilirsiniz read -u 7
:
while read -u 7 filename;do
ans=;while [ -z "$ans" ];do
read -p "Process file '$filename' (y/n)? " -sn1 foo
[ "$foo" ]&& [ -z "${foo/[yn]}" ]&& ans=$foo || echo '??'
done
if [ "$ans" = "y" ] ;then
echo Yes
echo "Processing '$filename'."
else
echo No
fi
done 7<file.txt
done
Kapatmak için fd/7
:
exec 7<&- # This will close file descriptor 7.
ls -l /dev/fd/
Not: Paralel işlemle birçok I / O yaparken bu sözdiziminin yararlı olabileceği için çarpıcı sürüme izin verdim:
mkfifo sshfifo
exec 7> >(ssh -t user@host sh >sshfifo)
exec 6<sshfifo
cat file.txt | tr \\n \\0 | xargs -0 -n1 chmod 755
tr \\n \\0 <file.txt |xargs -0 [command]
tarif ettiğiniz yöntemden yaklaşık% 50 daha hızlıdır.
Evet.
while read in; do chmod 755 "$in"; done < file.txt
Bu şekilde bir cat
işlemden kaçınabilirsiniz .
cat
böyle bir amaç için neredeyse her zaman kötüdür. Yararsız Kedi Kullanımı hakkında daha fazla bilgi edinebilirsiniz .
cat
iyi bir fikirdir, ancak bu durumda, belirtilen komutxargs
chmod
(yani dosyadaki her satır için gerçekten bir komut çalıştırın).
read -r
(standart girişten tek bir satır okur read
olmadan -r
bunu istemiyoruz, yorumlayan ters eğik)."
güzel bir seçiciniz varsa (örneğin bir dizindeki tüm .txt dosyaları) şunları yapabilirsiniz:
for i in *.txt; do chmod 755 "$i"; done
veya bir varyantınız:
while read line; do chmod 755 "$line"; done <file.txt
Girişte boşluk olmadığınızı biliyorsanız:
xargs chmod 755 < file.txt
Yollarda boşluk varsa ve GNU xargs'ınız varsa:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
xargs
sağlamdır. Bu araç çok eskidir ve kodu şiddetle tekrar gözden geçirilir . Amacı başlangıçta mermi sınırlamaları (64kchar / line falan) konusunda çizgiler oluşturmaktı. Şimdi bu araç çok büyük dosyalarla çalışabilir ve son komuta çatal sayısını çok azaltabilir. Cevabımı gör ve / veya man xargs
.
brew install findutils
) GNU xargs kurabilir ve gxargs
bunun yerine GNU xargs'ı çağırabilirsiniz , örneğingxargs chmod 755 < file.txt
Komutunuzu her satır için paralel olarak çalıştırmak istiyorsanız GNU Paralel kullanabilirsiniz
parallel -a <your file> <program>
Dosyanızın her satırı bağımsız değişken olarak programa aktarılır. Varsayılan parallel
olarak CPU'larınızın saydığı sayıda iş parçacığı çalıştırır. Ama ile belirtebilirsiniz-j
Bash etiketlediğinizi görüyorum, ancak Perl de bunu yapmanın iyi bir yolu olurdu:
perl -p -e '`chmod 755 $_`' file.txt
Doğru dosyaları aldığınızdan emin olmak için bir regex uygulayabilirsiniz, örneğin yalnızca .txt dosyalarını işlemek için:
perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt
Olanları "önizlemek" için, ters tırnakları çift tırnak işareti ile değiştirin ve başına print
:
perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
chmod
işlevi var
perl -lpe 'chmod 0755, $_' file.txt
- kullanım -l
"otomatik chomp" özelliği için
Dosyayı işlemek için size daha fazla esneklik kazandırabilecek AWK'yi de kullanabilirsiniz.
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
dosyanızda aşağıdaki gibi bir alan ayırıcısı varsa:
field1, field2, alan3
Sadece yaptığınız ilk alanı elde etmek için
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
GNU Belgeleri hakkında daha fazla bilgiyi https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple
Mantık diğer birçok amaç için de geçerlidir. Ve / home / dosya sisteminden her kullanıcının .sh_history nasıl okunur? Ya bin tane varsa?
#!/bin/ksh
last |head -10|awk '{print $1}'|
while IFS= read -r line
do
su - "$line" -c 'tail .sh_history'
done
İşte https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh betiği
Geç olduğunu biliyorum ama yine de
Herhangi bir şans eseri \r\n
yerine, windows kaydedilmiş metin dosyası ile \n
çalışırsanız, komutunuz argüman olarak okuma satırından sonra sth varsa, çıktı ile karışabilirsiniz. Öyleyse kaldırın \r
, örneğin:
cat file | tr -d '\r' | xargs -L 1 -i echo do_sth_with_{}_as_line
xargs
gibi, muhtaç, bazı özellikler bu tür cevaplanması için initialy inşa edildi cari ortamında uzun mümkün olduğunca komutu bina talebinde bulunmak içinchmod
, mümkün olduğunca az bu durumda azaltılması çatallar efficience sağlamak.while ;do..done <$file
1 dosya için 1 çatal çalışan implie.xargs
bin dosya için 1 çatal çalıştırabilir ... güvenilir bir şekilde.