2011-07-13 20 views
4

findコマンドで見つかったすべてのファイルに対して展開シェルコマンドを実行しようとしています。私は-execとxargsを試しましたが、どちらも失敗しました。誰も私の理由を説明することはできますか?私は記録のためにマックにいる。実行時に展開を実行


find . -name "*.php" -exec expand -t 4 {} > {} \;

これは、だけではなく、個々の見つかったファイル自体を上書きし、すべての出力を持つファイル{}を作成します。


find . -name "*.php" -print0 | xargs -0 -I expand -t 4 {} > {}

そして、これだけ

4 {} 
xargs: 4: No such file or directory 

答えて

8

あなたのコマンドでは、二つの理由のために動作しません出力します。

  1. 出力リダイレクトはシェルによって行われ、findでは実行されません。つまり、シェルはにfindの出力をリダイレクトします。
  2. リダイレクトはすぐに発生します。これは、ファイルがexpandコマンドで読み取られる前に書き込まれることを意味します。したがって、コマンドの出力を入力ファイルにリダイレクトすることはできません。

残念ながら、expandはファイルに出力することはできません。したがって、出力リダイレクトを使用する必要があります。 bashを使用する場合は、expandを実行するfunctionを定義し、出力を一時ファイルにリダイレクトし、一時ファイルを元のファイルに戻すことができます。問題は、findが新しいシェルを実行してexpandコマンドを実行することです。

しかし、解決策があります:

expand_func() { 
    expand -t 4 "$1" > "$1.tmp" 
    mv "$1.tmp" "$1" 
} 

export -f expand_func 

find . -name \*.php -exec bash -c 'expand_func {}' \; 

あなたはexport -fを使用して、サブシェルに機能expand_funcを輸出しています。そして、find -execを使用してexpand自体を実行することはありませんが、エクスポートされたexpand_funcを実行する新しいbashを実行します。

0

「エキスパンド」は本当に問題にはなりません。 代わりにsedを使うことができます:

find . -name "*.php" | xargs sed -i -e 's/\t/ /g' 
関連する問題