web-dev-qa-db-ja.com

ファイルの各行に対してどのようにコマンドを実行しますか?

たとえば、現在、次のコマンドを使用して、Unixパスをファイルに書き込んだいくつかのファイルを変更しています。

cat file.txt | while read in; do chmod 755 "$in"; done

よりエレガントで安全な方法はありますか?

122
hawk

ファイルが大きすぎず、すべてのファイルが適切な名前(スペースや引用符のような他の特殊文字なし)である場合、単純に次のことができます。

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)
85
F. Hauri

はい。

while read in; do chmod 755 "$in"; done < file.txt

これにより、catプロセスを回避できます。

catは、ほとんどの場合、このような目的には不適切です。 Cat。の無駄な使用の詳細を読むことができます

131
P.P.

niceセレクター(たとえば、ディレクトリ内のすべての.txtファイル)がある場合は、次のようにします。

for i in *.txt; do chmod 755 "$i"; done

bash for loop

またはあなたのバリアント:

while read line; do chmod 755 "$line"; done <file.txt
13
d.raev

入力に空白がないことがわかっている場合:

xargs chmod 755 < file.txt

パスに空白が含まれている可能性があり、GNU xargsがある場合:

tr '\n' '\0' < file.txt | xargs -0 chmod 755
13
glenn jackman

各行でコマンドを並行して実行する場合は、 GNU Parallel を使用できます

parallel -a <your file> <program>

ファイルの各行は、引数としてプログラムに渡されます。デフォルトでは、parallelはCPUがカウントする数のスレッドを実行します。ただし、-jで指定できます

10
janisz

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
2
1.618

AWKを使用して、ファイルをより柔軟に処理することもできます。

awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt

ファイルに次のようなフィールドセパレータがある場合:

field1、field2、field3

最初のフィールドのみを取得するには

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

0
brunocrt

ロジックは他の多くの目的に適用されます。そして、各ユーザーの.sh_historyを/ home /ファイルシステムから読み取る方法は?それらが何千もある場合はどうなりますか?

#!/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

0
igor.monteiro