STDINで行を繰り返してシェルコマンドを実行するには?

STDINで行を繰り返してシェルコマンドを実行するには?

STDINから取得した各行に対してシェルコマンドを実行したいと思います。

この場合はxargs mv。たとえば、次の2行が与えられます。

mfoo foo
mbar bar

私は走りたいです:

xargs mv mfoo foo
xargs mv mbar bar

私は次の戦略を試しましたrubyawkxargs。しかし、私は何かが間違っています。

のみxargs:

$ echo "mbar bar\nmbaz baz" | xargs mv
usage: mv [-f | -i | -n] [-v] source target
       mv [-f | -i | -n] [-v] source ... directory

渡すawk

$ echo "mbar bar\nmbaz baz" | awk '{ system("xargs $0") }'

渡すruby

$ echo "mbar bar\nmbaz baz" | ruby -ne '`xargs mv`'
$ ls
cat  foo  mbar mbaz

質問がいくつかあります:

  • 私がしたいことをどうすればいいですか?
  • 私が試すたびに何が間違っていますか?
  • 私がやろうとしていることを「考える」より良い方法はありますか?

xargs私は特に次のことがうまくいくので、やりたいことがうまくいかないという事実に混乱しています。

$ echo "foo\nbar" | xargs touch
$ ls
bar foo

答え1

echo "mbar bar\nmbaz baz" | xargs mv

何が起こっているかを確認するには、xargsこのオプションを使用する必要があります。-tしたがって、上記の場合に を使用して呼び出すと、次のxargsよう-tな内容が表示されます。

mv mbar bar mbaz baz

したがって、これは明らかに正しくありません。空腹のワニのように、パイプを介してxargs供給されるすべてのパラメータを食べますecho。したがって、crocのパラメータリリースを制限する方法が必要です。行ごとに要求するため、-lまたは-Lfor POSIXオプションが必要です。

echo "mbar bar\nmbaz baz" | xargs -l -t mv

POSIX方式:

echo "mbar bar\nmbaz baz" | xargs -L 1 -t mv

mv mbar bar
mv mbaz baz

これがあなたが望むものです。ファタイ

答え2

次のように行くことができます:

echo -e "foo bar\ndoo dar" | xargs -n 2 mv

ファイルから読む:

cat lines.txt | xargs -n 2 mv

または

xargs -a lines.txt -n 2 mv

答え3

xargs期待どおりに動作しない場合があります。この質問に関する@MichaelHomerのコメントを参照してください。

xargs mv mfoo foo入力を待って入力された各行に対してmfoo foo $x_1 $x_2 $x_3...mvを実行します。$x_n@マイケルホーマー

これを読むと確認できます。xargsマニュアルページ:

説明
xargs ユーティリティは、標準入力からスペース、タブ、改行、およびファイルの末尾で区切られた文字列を読み取り、これらの文字列を引数として使用してユーティリティを実行します。

xargs実際、最初の引数として指定されたコマンドラインユーティリティに引数が指定された場合、改行は無視されるように見えます。たとえば、改行文字に何が起こるかを見てみましょう。

$ echo "foo bar\ncat dog"
foo bar
cat dog
$ echo "foo bar\ncat dog" | xargs echo
foo bar cat dog

この動作は次のように制御できます。-nバナー:

-n 数値


ユーティリティが呼び出されるたびに、標準入力から取得される最大引数の数を設定します。

前の例に戻り、xargs2つのパラメータのみを取り出して終了するには、次のようにします。@ddnomadのアプローチ:

$ echo "foo bar\ncat dog" | xargs -n 2 echo
foo bar
cat dog

また、Rakesh Sharmaの回答のコメントに示すように、BSDではxargsフラグを使用して読み取る回数を指定できます-L。マニュアルページから:

-Lサイズ

このユーティリティは、読み取った各番号軸に対して呼び出されます。 EOF に到達して
読み取った行数より少ない場合は、使用可能な行としてユーティリティが呼び出されます。

テストに役立つ-tスイッチもあります。

例をもう一度見てみると、次のすべての方法が機能しますが、この例の目的は、2番目の例の方が優れています。

$ echo "foo bar\ncat dog" | xargs -n 2 echo
foo bar
cat dog
$ echo "foo bar\ncat dog" | xargs -L 1 echo
foo bar
cat dog

マニュアルページの注意事項:

-Lおよび-nオプションは相互に排他的です。提供された最後のオプションが使用されます。

答え4

xargsを使用しない非常に単純なソリューションがあります。
この関数を定義します。

$ mv2() { while (($# >1 )); do echo mv "$1" "$2"; shift 2; done; }

次に、必要なファイル名のリストを使用して呼び出します(改行は必要ありません)。

$ mv2 mbar bar mbaz baz
mv mbar bar
mv mbaz baz

エコーを削除し、機能が実際に機能するようにします。

関連情報