回答:
これは、答えが1つだけではないためです...
shell コマンドライン展開xargs 専用ツールwhile read いくつかのコメント付きwhile read -uインタラクティブ処理のfdために専用のを使用(サンプル)OPリクエストについて:fileにリストされているすべてのターゲットで実行chmodされるのxargsは、示されているツールです。しかし、他のいくつかのアプリケーションでは、少量のファイルなど...
ファイルが大きすぎず、すべてのファイルに適切な名前が付けられている場合(スペースや引用符などのその他の特殊文字なし)、shellコマンドライン展開を使用できます。単に:
chmod 755 $(<file.txt)
少量のファイル(行)の場合、このコマンドは軽いコマンドです。
xargs 適切なツールです大量のファイル、または入力ファイルのほとんどすべての行の場合 ...
多くの人にとってのbinutilsのように、ツールchown、chmod、rm、cp -t...
xargs chmod 755 <file.txt
に特別な文字や多くの行がある場合file.txt。
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
入力によってコマンドを正確に1回実行する必要がある場合:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
これはこのサンプルでは必要ありません。chmod複数のファイルを引数として受け入れますが、これは質問のタイトルと一致します。
いくつかの特別な場合のために、生成されたコマンドでファイル引数の場所を定義することもできますxargs:
xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
seq 1 5入力としてテストこれを試して:
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..
コマンドは、1行に1回実行されます。
while read とバリアント。OPが機能することを示しcat file.txt | while read in; do chmod 755 "$in"; doneますが、2つの問題があります。
cat |ある無用フォーク、と
| while ... ;doneなりますサブシェル環境は後disapearます;done。
したがって、これはより適切に記述できます。
while read in; do chmod 755 "$in"; done < file.txt
だが、
あなたはについて警告することができる$IFSとreadのフラグ:
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...
場合によっては、使用する必要があります
while IFS= read -r in;do chmod 755 "$in";done <file.txt
見知らぬファイル名の問題を回避するため。そして多分あなたが問題に遭遇した場合UTF-8:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txtのSTDIN読み取りfile.txtに使用している間、スクリプトをインタラクティブにすることはできません(STDINもう使用できません)。
while read -u、専用を使用してfd。構文:while read ...;done <file.txtにリダイレクトさSTDINれfile.txtます。つまり、プロセスが完了するまで、プロセスを処理することはできません。
インタラクティブツールを作成する場合はSTDIN、代替ファイル記述子の使用を避け、使用する必要があります。
定数ファイルディスクリプタは以下のとおりです。0のためのSTDIN、1のためのSTDOUTおよび2ためSTDERR。あなたはそれらを見ることができます:
ls -l /dev/fd/
または
ls -l /proc/self/fd/
そこから、ファイル記述子0としてとの間63(実際には、sysctlスーパーユーザーツールによって異なります)の未使用の番号を選択する必要があります。
このデモでは、fd を使用します7。
exec 7<file.txt      # Without spaces between `7` and `<`!
ls -l /dev/fd/
次に、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
閉じるにはfd/7:
exec 7<&-            # This will close file descriptor 7.
ls -l /dev/fd/
注意:この構文は、並列処理で多くのI / Oを実行するときに役立つため、ストライクバージョンを使用しました。
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]あなたが説明した方法よりも約50%高速です。
                    はい。
while read in; do chmod 755 "$in"; done < file.txt
これにより、catプロセスを回避できます。
cat良いアイデアですが、この場合には、指示されたコマンドがあるxargs
                    chmod(つまり、実際にはファイルの各行に対して1つのコマンドを実行する場合)に役立ちました。
                    read -r標準入力から1行を読み取ります(バックスラッシュreadを-r解釈しないと、必要ありません)。"
                    素敵なセレクターがある場合(たとえば、dir内のすべての.txtファイル)、次のようにできます。
for i in *.txt; do chmod 755 "$i"; done
またはあなたの変種:
while read line; do chmod 755 "$line"; done <file.txt
              入力に空白がないことがわかっている場合:
xargs chmod 755 < file.txt
パスに空白がある可能性があり、GNU xargsがある場合:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
              brew install findutils)を使用してmacOSにGNU xargsをインストールしてから、gxargs代わりにGNU xargsを呼び出すことができます。例gxargs chmod 755 < file.txt
                    行ごとにコマンドを並行して実行する場合は、GNU Parallelを使用できます。
parallel -a <your file> <program>
ファイルの各行は、引数としてプログラムに渡されます。デフォルトでparallelは、CPUの数と同じ数のスレッドが実行されます。しかし、あなたはそれを指定することができます-j
bashにタグを付けたようですが、Perlもこれを行うための良い方法です。
perl -p -e '`chmod 755 $_`' file.txt
正規表現を適用して、たとえば.txtファイルのみを処理するなど、適切なファイルを取得していることを確認することもできます。
perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt
何が起こっているのかを「プレビュー」するには、バッククォートを二重引用符で置き換え、先頭に追加しますprint。
perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
              chmod機能
                    perl -lpe 'chmod 0755, $_' file.txt- -l「オートチョップ」機能に使用する
                    AWKを使用してファイルをより柔軟に処理することもできます
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
ファイルに次のようなフィールドセパレータがある場合:
フィールド1、フィールド2、フィールド3
最初のフィールドのみを取得するには
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
GNUドキュメントhttps://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simpleで詳細を確認でき ます。
ロジックは他の多くの目的に適用されます。また、/ home /ファイルシステムから各ユーザーの.sh_historyを読み取る方法は?それらが数千ある場合はどうなりますか?
#!/bin/ksh
last |head -10|awk '{print $1}'|
 while IFS= read -r line
 do
su - "$line" -c 'tail .sh_history'
 done
ここにスクリプトhttps://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh
xargs同様に、必要性、いくつかの機能のこの種に答えるためで初期状態のビルドた現在の環境で可能な限りのようにコマンドを構築呼び出すためにchmod、できるだけ少ないこの場合、還元フォークが efficienceを確保します。while ;do..done <$file1つのファイルに対して1つのフォークを実行することを暗黙指定します。xargs1000のファイルに対して1フォークを実行できます...信頼できる方法で。