find
私はwithの出力を処理しようとしましたがparallel
、これは順番にシェルを呼び出します(一部のテキスト置換が必要です)。私は自分で説明できない奇妙な行動を観察しました。
各ディレクトリには複数のファイルがありますfile1.xtc
。file2.xtc
そのいくつかはfile1.part0002.xtc
。渡されたファイルにfind
その名前がある場合は、結果コマンドが次のように見えるように*.part000x.*
そのビットを削除する必要があります。*.part000x.*
command -f file1.part0001.xtc -s file1.tpr
find
andを使用してparallel
この効果を得ましたが、parallel
代替項目(特にビット{.}
)が十分ではありませんでした(.xtc
拡張子を削除して.part0001
そのままにしました)。したがって、出力を確認するために使用したコマンドは次のようになります。
find 1st 2nd 3rd -name '*.xtc' -print0 | parallel -0 sh -c 'name=""; name="{.}"; echo {.} ${name%.*}.tpr'
上記のコマンドを使用して最初に宣言し、空のname
文字列(またはその問題の他の項目)を割り当てると、結果は次のようになります。
file1.part0001 file1.tpr
必要に応じて(これは私のコマンドが使用する必要がある名前です)が、これを実行すると
find 1st 2nd 3rd -name '*.xtc' -print0 | parallel -0 sh -c 'name="{.}"; echo {.} ${name%.*}.tpr'
結果:
file1.part0001 .tpr
$name
または存在しないかのように動作します。
だから私の質問は次のようになります
- このような行動をする理由は何ですか?
- この問題を処理するための好ましい方法は何ですか?
ここで最初の質問はより重要です。上記で使用した方法は見栄えが良くありませんが、うまくいく解決策だからです。このようにテキストを置き換える必要があったのは今回が初めてではなく、この振る舞いはまだ私を恥ずかしくさせます。
出力sh --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
bash
上記のコマンドで代わりにインストールして使用した最新バージョンの出力sh
(同じ効果を得るために)(/usr/local/bin/bash --version
)
GNU bash, version 4.2.0(1)-release (i386-apple-darwin11.4.2)
答え1
あなたの問題はbashとは関係ありません。実際、parallel
runと言った後はsh
それを使用しないかもしれませんbash
。
問題は、ドキュメントが示すように、パラレルがxargsを実際に置き換えないことです。代わりに、引数を単一の文字列(間にスペースを含む)として累積してから、一連のコマンドとして解釈します。したがって、あなたの場合には、以下があります。
sh -c 'name="{.}"; echo {.} ${name%.*}.tpr'
これは次のように解釈されます。
sh -c 'name="{.}";
echo {.} ${name.*}.tpr
これは2つの別々のコマンドで、最初のコマンドsh -c
はサブシェル()で実行されるため、$name
2番目のコマンドには設定されません。
これで、文字列の先頭に何でも追加できますtrue
。たとえば、次のようになります。
sh -c 'true; name="{.}"; echo {.} ${name%.*}.tpr'
これは次のように解釈されます。
sh -c 'true'
name="{.}"
echo {.} ${name%.*}.tpr'
この場合、呼び出しはsh
本質的にワンタイムであり、name
setによって維持される環境で設定され、parallel
最後にsetecho
として呼び出されますname
。
したがって、最も簡単な解決策は不要な呼び出しを削除するようですsh
。
find 1st 2nd 3rd -name '*.xtc' -print0 |
parallel -0 'name={.}; echo {.} "${name%.*}.tpr"'
メモ:@StephaneChazelasが提供したヒントに従って、二重引用符を削除して{.}
周囲に追加しました${name%.*}.ptr
。並列参照は自己置換を使用するため、奇妙な方法で明示的な参照を妨げます。ただし、代替アイテムがトークン化される可能性がある場合、追加する必要があるシェル代替アイテムには引用符を追加しません。
何らかの理由でサブシェル(または特定のサブシェル)を本当に使用したい場合は、別のオプションは次のものを使用することです-q
:
find 1st 2nd 3rd -name '*.xtc' -print0 |
parallel -0 -q sh -c 'name="{.}"; echo "{.}" "${name%.*}.tpr"'
メモ:上記のように提案を調整しました。この場合、-q
代替項目への参照は明示的に禁止されるため、明示的に参照する必要があります。ただし、これはシェル引用符ほど正確ではないテキスト引用符です。代替引用符に二重引用符文字が含まれている場合、その文字はエスケープされず、明示的な引用符がオフになり、コマンドラインが中断され、効果的に挿入されます。コマンドインジェクションの脆弱性($
、`
または\
文字を含むファイル名)。このため、何よりも-q
このオプションはお勧めできません。