回答:
while readループを使用する:
: > another_file ## Truncate file.
while IFS= read -r LINE; do
command --option "$LINE" >> another_file
done < file
別の方法は、ブロックごとに出力をリダイレクトすることです:
while IFS= read -r LINE; do
command --option "$LINE"
done < file > another_file
最後はファイルを開くことです:
exec 4> another_file
while IFS= read -r LINE; do
command --option "$LINE" >&4
echo xyz ## Another optional command that sends output to stdout.
done < file
コマンドの1つが入力を読み取る場合、コマンドがそれを食べないように、別のfdを入力に使用することをお勧めします(ここではksh、zshまたはbashfor -u 3を<&3代わりに移植可能に使用します)。
while IFS= read -ru 3 LINE; do
...
done 3< file
最後に、引数を受け入れるために、次のことができます。
#!/bin/bash
FILE=$1
ANOTHER_FILE=$2
exec 4> "$ANOTHER_FILE"
while IFS= read -ru 3 LINE; do
command --option "$LINE" >&4
done 3< "$FILE"
実行できるもの:
bash script.sh file another_file
余分なアイデア。でbash、使用readarray:
readarray -t LINES < "$FILE"
for LINE in "${LINES[@]}"; do
...
done
注:IFS=行の値の先頭と末尾のスペースを削除しても構わない場合は、省略できます。
別のオプションはxargsです。
GNUの場合xargs:
< file xargs -I{} -d'\n' command --option {} other args
{} テキスト行のプレースホルダーです。
その他にxargsはがありませんが-d、一部は-0NUL区切りの入力用です。これらを使用すると、次のことができます。
< file tr '\n' '\0' | xargs -0 -I{} command --option {} other args
Unix準拠のシステム(-IPOSIXではオプションで、Unix準拠のシステムでのみ必要)では、入力を前処理して、次の形式で行を引用する必要がありますxargs。
< file sed 's/"/"\\""/g;s/.*/"&"/' |
xargs -E '' -I{} command --option {} other args
ただし、一部のxargs実装では、引数の最大サイズに非常に低い制限があることに注意してください(たとえば、Solarisでは255、Unix仕様で許可されている最小)。
質問を正確に保つ:
#!/bin/bash
# xargs -n param sets how many lines from the input to send to the command
# Call command once per line
[[ -f $1 ]] && cat $1 | xargs -n1 command --option
# Call command with 2 lines as args, such as an openvpn password file
# [[ -f $1 ]] && cat $1 | xargs -n2 command --option
# Call command with all lines as args
# [[ -f $1 ]] && cat $1 | xargs command --option
私が見つけた最良の答えは:
for i in `cat`; do "$cmd" "$i"; done < $file
編集:
... 4年後 ...
いくつかのダウン投票といくつかの経験の後、私は今、以下をお勧めします
xargs -l COMMAND < file
do "$cmd" "$i";理由がない限り、シェル変数への参照を常に引用する必要があります(のように)。ファイルに*単語としてaが含まれている場合、コードが実行され$cmd *、もちろん、現在のディレクトリ内のファイルのリストを使用してコマンドが実行されます。
zsh、`cat`は既に展開されます*(の$i展開がいくつかを`cat`導入する場合、引用符で囲まれていないワイルドカード(2回目のラウンド)を展開できます)。いずれにせよ、そのアプローチは確かに間違っています。
sed "s/'/'\\\\''/g;s/.*/\$* '&'/" <<\FILE |\
sh -s -- command echo --option
all of the{&}se li$n\es 'are safely shell
quoted and handed to command as its last argument
following --option, and, here, before that echo
FILE
--option all of the{&}se li$n\es 'are safely shell
--option quoted and handed to command as its last argument
--option following --option, and, here, before that echo
ed file.txt
%g/^/s// /
2,$g/^/-,.j
1s/^/command/
wq
chmod 755 file.txt
./file.txt
ファイルのすべての行を引数として単一のコマンドに渡します。つまり、
command line1 line2 line3 ....
--option各行の前にフラグが必要な場合は、2番目のコマンドを次のように変更します。
%g/^/s// --option /
'、"、<、>、;、など(3)これは、不要な一時ファイルを作成します。(4)このようなことは一般に「ヒアドキュメント」で行われます。(5)edコマンドが不器用です。最初の2つのコマンドはに減らすことができる%s/^/ /と%j。
<file xargs -L 1 -I{} command --option {} other args