GNU Parallelの各入力パラメータを作業ディレクトリとして使用する

GNU Parallelの各入力パラメータを作業ディレクトリとして使用する

GNU Parallelを使用して各入力引数に対してコマンドを実行してみました。その引数をコマンドの作業ディレクトリとして使用しました(コマンドラインに追加せず)。

基本的に私がすべきことは次のとおりです。

/foo -> "cd /foo; mycmd"
/bar -> "cd /bar; mycmd"
/baz -> "cd /baz; mycmd"

Parallelは代替文字列を--workdirサポートして、{}私が望むことをするようです。

--workdir mydir
--wd mydir

ジョブは mydir ディレクトリで実行されます。デフォルトは、ローカルコンピュータの現在のディレクトリとリモートコンピュータのログインディレクトリです。
<...>
mydir には GNU Parallel の代替文字列を含めることができます。

-n0引数がコマンドラインに追加されるのを防ぐために、または以下を試しました-N0

--max-args 最大パラメータ
-n 最大パラメータ

コマンドラインごとに最大 max-args 個の引数を使用します。
<...>
-n 0は1つのパラメータを読み込みますが、コマンドラインに0つのパラメータを挿入することを意味します。

しかし、これはうまくいかないようです。

$ mkdir -p $HOME/{foo,bar,baz}
$ printf '%s\n' $HOME/{foo,bar,baz} | parallel --workdir '{}' -n0 'pwd'
parallel: Error: Cannot change into non-executable dir : No such file or directory

前のスペースに注意してください:。これは、GNU並列処理のミスではなく、workdirが空の文字列として評価されることを示します。前に固定文字列を追加すると、{}これが明らかになります。この場合、すべてのpwdは対応する固定文字列を印刷します。

$ printf '%s\n' $HOME/{foo,bar,baz} | parallel --workdir '/{}' -N0 'pwd'       
/
/
/

私は何が間違っていましたか?

答え1

私は最も単純なものが次のようになると信じています:

printf '%s\n' $HOME/{foo,bar,baz} | parallel 'cd {} && myprg'

あなたできるUsed--workdirですが、この場合は明らかに機能しません。 GNU Parallelでは、コマンドテンプレートに代替文字列と{}含めるパラメータが必要なことがよくあります--workdir

thenを使用すると、thenは空で失敗する可能性がある-n0ため役に立ちません。使用する場所ごとに同じ文字列で評価されます。{}--workdir{}

したがって、解決策はを使用することですが、{}害のない場所で使用することです。

parallel --workdir {} 'true dummy {}; myprg' ::: $HOME/{foo,bar,baz}

または、{==}ビルドコマンドの静的部分を使用します。

parallel --workdir {} '{= $_="myprg" =}' ::: $HOME/{foo,bar,baz}

個人的に私はこのcd {}バージョンを好みます。何をしたいのかを確認する方が簡単だと思います。

答え2

AFAICTは引数のすべてのコマンドを拡張する--workdirためのものではありません。{...}それにもかかわらず、GNUはparallelシェルを実行してユーザーが提供したコードを解釈するので、いつでも次のことができます。

... | PARALLEL_SHELL=sh parallel 'CDPATH= cd -P -- {} && mycmd'

(これは実行するシェルを決定するための経験的な方法shに頼るのではなく、シェルを強制し、いくつかの問題を解決します。)parallelcd

GNU機能がまったく必要ない場合は、GNUでparallelGNUを使用すると、GNUとシェルのオーバーヘッドと信頼できないシェル組み込み機能を回避できます。xargsenvparallelcd

... | xargs -rd '\n' -P8 -I{} env -C {} mycmd

関連情報