[解決済み】ファイルの各行に対してコマンドを実行する方法とは?
質問
例えば、今、私は、Unixのパスをファイルに書き込んだいくつかのファイルを変更するために、次のように使っています。
cat file.txt | while read in; do chmod 755 "$in"; done
もっとエレガントで安全な方法はないのでしょうか?
どのように解決するのですか?
ファイルを一行ずつ読んで、コマンドを実行する。4つの回答
答えは1つだけではないからです...。
-
shell
コマンドライン展開 -
xargs
専用ツール -
while read
備考 -
while read -u
専用fd
のために インタラクティブ 処理 (サンプル)
OPリクエストについて。
走行
chmod
ファイルにリストされたすべてのターゲット上で
,
xargs
は、指示されたツールです。しかし、他のアプリケーション、少量のファイルなどでは、....
0. ファイル全体をコマンドライン引数として読み込む。
If your file is not too big and all files are *well named* (without spaces or other special chars like quotes), you could use *`shell` command line expansion*. Simply:
chmod 755 $(<file.txt)
For small amount of files (lines), this command is the lighter one.
1.
xargs
は正しいツールです
For bigger amount of files, or almost ***any*** number of lines in your input file...
For many *binutils* tools, like `chown`, `chmod`, `rm`, `cp -t` ...
xargs chmod 755 <file.txt
If you have special chars and/or a lot of lines in `file.txt`.
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
if your command need to be run exactly 1 time by entry:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
This is not needed for this sample, as `chmod` accept multiple files as argument, but this match the title of question.
For some special case, you could even define location of file argument in commands generateds by `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回 .
2.
while read
とバリアントがあります。
OPにあるように
cat file.txt | while read in; do chmod 755 "$in"; done
はうまくいくのですが、2つの問題があります。
- `cat |` is an *useless fork*, and
- `| while ... ;done` will become a *subshell* where environment will disapear after `;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...
In some case, you may need to use
while IFS= read -r in;do chmod 755 "$in";done <file.txt
For avoiding problems with stranges filenames. And maybe if you encouter problems with *`UTF-8`*:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txt
-
を使用している間
STDIN
読み込み用file.txt
あなたのスクリプトは インタラクティブ (を使用することはできません。STDIN
を追加しました)。
3.
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/
注意:私は ストライク この構文は、Parallels プロセスで多数の I/O を行う場合に便利だからです。
mkfifo sshfifo
exec 7> >(ssh -t user@host sh >sshfifo)
exec 6<sshfifo
関連
-
[解決済み] Bashでの動的な変数名
-
[解決済み] grepの出力に含まれる重複を削除する
-
[解決済み] Bashで通常のファイルが存在しないかどうかを判断する方法を教えてください。
-
[解決済み] Bashでコマンドライン引数を解析するには?
-
[解決済み] Bashでコマンドの出力に変数を設定するにはどうすればよいですか?
-
[解決済み] Bashで標準出力と標準エラーの両方をファイルにリダイレクトして追記する方法
-
[解決済み] Git上でシェルコマンドを実行する際に使用するSSH-keyの秘密鍵を指定する方法は?
-
[解決済み] コマンドラインから .bash_profile を再読み込みする方法は?
-
[解決済み] コマンドラインからの 'git commit -m' に改行を追加する
-
[解決済み] Bashでの単一行whileループの構文
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】bashでjsonファイルを解析するために、jqの出力にあるダブルクオートを削除する方法は?
-
[解決済み】shでJenkinsのステージから他のステージに変数を渡す
-
[解決済み] 部分的にコピーされたファイルでscpを再開する方法は?[クローズド]です。
-
[解決済み] Bashで文字列から改行を削除する方法
-
[解決済み] OS X で 'find' コマンドを使用して 'sed' を使用するとエラーが発生する。"無効なコマンドコードです。"
-
[解決済み] 値がベースに対して大きすぎる(エラートークンは "08")[重複]
-
[解決済み] zip警告 - 名前が一致しない
-
[解決済み] Bash/Terminalで複数行の環境変数を書き出す方法 例: RSA秘密鍵
-
[解決済み] Bashで最新のディレクトリを変数に取得する
-
[解決済み] あいまいなリダイレクト」エラーが発生する