回答:
これは、答えが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 <$file
1つのファイルに対して1つのフォークを実行することを暗黙指定します。xargs
1000のファイルに対して1フォークを実行できます...信頼できる方法で。