2016-03-23 10 views
3

私は並列に多くのコマンドを実行しようとしていますが、まず入力に対して何らかの文字列操作を行う必要があります。下の例はどのように動作させることができますか?引数をxargsからbashに渡して処理の変数として受け取ります

find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v={}; echo $v" 

これを使用すると、$vはnullです。 {}の値として保存されないのはなぜですか?

+0

それは、コマンドラインではなく、sh' 'へxargsはの呼び出しによって展開されていますので、あなたの' $のv'がnullです。ドル記号が間違ったシェルによって解釈されないようにするには、一重引用符を使用します。異なる引用符がどのように機能するかについてのいくつかの洞察については、[この回答](http://stackoverflow.com/a/9712555/1072112)をチェックしてください。 – ghoti

答えて

2

$vの前にの文字列がxargsに渡されます。

findコマンドでサブディレクトリ./stuffが見つかったとします。

最初に親のbashシェル(findコマンドを入力したシェル)は、文字列が二重引用符で囲まれているため、$vを展開します。変数vに現在値が設定されていないため、空の文字列に展開されます。

次に、引数はこの表示されますこれは、xargsに渡されます:次にv={}; echo

を、xargsがパイプから./stuffを読んで、そして最後に、shコマンドがで実行される./stuff

{}を交換しますxargsおよびshは次のようになります。v=./stuff; echo

この問題を解決するには、$のようにして、親シェルが展開しないようにするか、単一引用符を使用して変数展開を回避します。彼らにスペースを持つ任意のディレクトリ名が最終shコマンドで問題を起こさないように、あなたはまた、おそらく文字列を引用符で囲む必要があります。

find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v=\"{}\"; echo \"\$v\"" 

OR

find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c 'v="{}"; echo "$v"' 

コマンドのいずれかを使用すると、最終的shプロセスをv="./stuff"; echo "$v"

ちなみに、実際に起こっていることを自分自身で確認する方法の1つは、親シェルでvの値を設定してから実行します元のコマンド。シェルは$vを任意の値に展開し、その値がfindで見つかるすべてのディレクトリに対して繰り返されることがわかります。 GNUで

$ v=foobar 
$ find . -mindepth 1 -type d | xargs -n 1 -P 20 -i sh -c "v={}; echo $v" 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
foobar 
... 
0

あなたがどうなるパラレル:

find . -mindepth 1 -type d | parallel -P 20 'v={}; echo "$v"' 
関連する問題