2

パターン *.xml に一致するすべてのファイルを再帰的に見つけて、その中のコードを削除しようとしています。

これは私が思いついたものです:

  • すべての .xml ファイルを見つけて行を削除する
  • の最初の出現から の最初の出現def=somethingまで</box>

find config/view -type f -name "*.xml" -exec sed -n '/def=something/,/<\/box>/!p' > tmp.xml {} \; -exec mv tmp.xml {} \;

ディレクトリ内の1つのファイルに対しては正常に機能しますが、次のようになります。

mv: cannot access tmp.xml

多くのファイルを含むディレクトリで呼び出すと

スクリプトのどこにバグがありますか? それとも、これを行うためのより良い/より簡単な方法がありますか??

4

2 に答える 2

2

>-execシェル構造であり、プライマリでは使用できません。execその引数は、シェルによって処理されるのではなく、ファミリ内のシステム コールの 1 つに直接渡されます。andは、リダイレクトではなく、に渡す 2 つの追加の文字列引数としてfind扱われるため、作成されることはありません。>tmp.xmlsedtmp.xml

1 つのオプションは、ファイルごとにシェルを明示的に開始することです。

find config/view -type f -name "*.xml" -exec \
  sh -c "sed -in '/def=something/,/<\/box>/!p' {} > tmp.xml && mv tmp.xml {}"

もう 1 つは、fedorqui が提案したように、オプションを使用sedしてアトミック ファイル操作自体を処理できるようにすることです (の使用法は実装によってわずかに異なることに注意してください。詳細については、マニュアル ページを確認してください)。-i-ised

于 2013-07-03T14:56:15.740 に答える
2

バグは、の-exec sedステートメントでfind、実行していないことです:

sed -n '/def=something/,/</box>/!p' > tmp.xml {}

(リダイレクトあり)。

実際、あなたの行は次と同等です:

find config/view -type f -name "*.xml" -exec sed -n '/def=something/,/<\/box>/!p' {} \; -exec mv tmp.xml {} \; > tmp.xml

つまり、すべての出力がfindfile にリダイレクトされますtmp.xml。次に、最初のファイルが見つかった後、tmp.xml は (移動されたため) もう存在せず、すべてが台無しになります!

これを修正するには、fedorqui の回答に示されているように、インライン編集を使用できます。

find config/view -type f -name "*.xml" -exec sed -i -n '/def=something/,/<\/box>/!p' {} +

+(行末の に注意してください)、または次のことができます。

find config/view -type f -name "*.xml" -exec bash -c 'sed -n "/def=something/,/<\/box>/!p" "$0" > tmp.xml; mv tmp.xml "$0"' {} \;

しかし、それはそれほど良くありません。sedただし、フラグがサポートされていない場合-i(GNUがサポートしている場合) には便利ですsed

于 2013-07-03T14:59:06.857 に答える