2012-04-19 56 views
0

私は現在のディレクトリとすべてのサブdirecotiresを移動し、相続人.SQLあいまいなリダイレクト

にコード

HEADER="--SQL HEADER" 

for f in 'find . -name *.sql'; 
do 
     echo $f 
     echo -e $HEADER > $f.tmp; 
     FNAME=${f//\//_/}; 
     echo -e "\n\n--MORE ANNOTATIONS ${FNAME%.*}:1" >> $f.tmp; 
     cat $f >> $f.tmp; 
     mv $f.tmp $f; 
     rm $f.tmp 
done; 

イムaのスニペットを終了し、各ファイルにいくつかの注釈を追加しようとしていますbashのでは初心者ので、私はエラーの一部を考える私が得るループ と検索文の原因である可能性があります取得しますが、これは誤りであるイム

find . -name X.sql A.sql W.sql E.sql S.sql 
./annotate.sh: line 6: $f.tmp: ambiguous redirect 
./annotate.sh: line 8: $f.tmp: ambiguous redirect 
./annotate.sh: line 9: $f.tmp: ambiguous redirect 
mv: invalid option -- n 
Try `mv --help' for more information. 
rm: invalid option -- n 
Try `rm --help' for more information. 

任意のヘルプは大だろうapprec =)

答えて

3

ここに問題があります。あなたの "エコー"、それを離れて与える:

echo $f 

出力

find . -name X.sql A.sql W.sql E.sql S.sql 

私は問題はあなたがストレート単一findコマンドで引用符( '')、代わりにバッククォートを( ``)持っていると思います。だから、実際には実行されていませんが、単にワイルドカードを展開しています。

あなたはそれを見つけるために、渡された代わりのシェルで評価しますので、ワイルドカードを引用する必要がある場合があります

for f in `find . -name \*.sql`; 

はしかし、あなたが使用したい場合は、対処すべきスクリプト内のいくつかの問題があり、それは複数回です。 ormaaj's answerを参照してください。

+5

+1との混同を避ける(とボーナスとしてネスティングが可能)にする、それは '$(コマンド)'形式の代わりに、バッククォート変種 '\'コマンドを使用することをお勧めします\ ''。 –

+1

いいえ... 'for'とバッククォートを使ってファイルを反復することはお勧めしません(指摘したように、' $() 'を使います)。あなたは最も直ちに問題を指摘したので、-1ではありません。 – ormaaj

+0

正解、これを指摘してくれてありがとう。シェルスクリプトを書く方法を教えようとするのではなく、単にその質問に答えるだけでした。 – theglauber

2

すでに指摘したように、findは実際に実行されていないという問題があります。しかし、このパターンは非常に間違っています。出力を単語に分割するには引用符を必要としません。ファイル名に改行を含めることができるため、パス名展開が無効になっても問題になります。

-execを使用することをお勧めします。

find . -name '*.sql' -exec scriptname {} + 

また、(これはバッシュの最新バージョンであると仮定した場合)、globstarを使用していないfind(:

#!/usr/bin/env bash 
header="--SQL HEADER" 

for f in "[email protected]"; do 
    echo "$f" >&2 
    fname=${f//\//_/} 

    cat - "$f" <<EOF >"$f.tmp" 
    ${header}$'\n\n' 
    --MORE ANNOTATIONS ${fname%.*}:1 
    EOF 

    mv "$f.tmp" "$f" 
done 

は次に、このようなfindを実行します。最初のファイルとchmod u+x scriptnameにこのスクリプトを書きますkshにも同様の機能があります)。これはジョブによって遅くなるかもしれません - シェルはファイルのリストをあらかじめ生成しなければなりません。あなたはバッシュ4持っているとあれば

#!/usr/bin/env bash 
shopt -s globstar 

for f in ./**/*.sql; do 
    ... 

また、必要なGNUユーティリティとシステムは、-print0を使用しています。

find . -name '*.sql' -print0 | while IFS= read -rd '' f; do 
    # <body of the above for loop here> 
done 

参照:http://mywiki.wooledge.org/UsingFind

関連する問題