2013-07-11 9 views
6

findを含む長いコマンドを作成しようとしています。私は無視したいディレクトリの配列を持っており、このディレクトリをコマンドに書式化したい。このへBash配列:配列内の各要素に追加およびプリペンド

declare -a ignore=(archive crl cfg) 

は基本的に、私はこの配列を変換したい

-o -path "$dir/archive" -prune -o -path "$dir/crl" -prune -o -path "$dir/cfg" -prune 

この方法で、私は単純に配列にディレクトリを追加することができ、かつfindコマンドは、それに応じて調整されます。

はこれまでのところ、私が先頭に追加または

${ignore[@]/#/-o -path \"\$dir/} 
${ignore[@]/%/\" -prune} 

を使用して追加する方法を考え出したしかし、私はこれらを組み合わせて、同時に先頭に追加し、配列の各要素に追加する方法がわかりません。

+0

いいアイデアのようですね。 $ {var/x/y}の各置換をサポートするには、配列の複数のレベル(コピー)を持つ必要があると思います。私は '$(echo $ {ig [@]} | sed/a/b/g; s/c/d/g; s/d/e $ /; s/^ f/g/')) 'となります。がんばろう! – shellter

答えて

12

同時に行うことはできません。彼らは関与スペースがあっても、配列はそれぞれ置換後の3つの要素が含まれていることを確認し - 括弧と二重引用符に注意してください

ignore=(archive crl cfg     ) 
ignore=("${ignore[@]/%/\" -prune}"  ) 
ignore=("${ignore[@]/#/-o -path \"\$dir/}") 

echo ${ignore[@]} 

:幸いにも、あなたがする必要はありません。

+0

より良い!皆さんお元気で。 – shellter

+1

これは本当にセクシーです! – jh314

+0

名前を引用しようとしましたが、完璧ではありません。もし 'ignore'に' ''のような奇妙なものが含まれていたら。 – musiphil

2

次のスイッチを持っているものxargsでのみ動作し

私が右理解していれば、

declare -a ignore=(archive crl cfg) 
a=$(echo ${ignore[@]} | xargs -n1 -I% echo -o -path '"$dir/%"' -prune) 
echo $a 

プリント

-o -path "$dir/archive" -prune -o -path "$dir/crl" -prune -o -path "$dir/cfg" -prune 
:あなたがすべき、一般的には

-I replstr 
     Execute utility for each input line, replacing one or more occurrences of replstr in up to replacements 
     (or 5 if no -R flag is specified) arguments to utility with the entire line of input. The resulting 
     arguments, after replacement is done, will not be allowed to grow beyond 255 bytes; this is implemented 
     by concatenating as much of the argument containing replstr as possible, to the constructed arguments to 
     utility, up to 255 bytes. The 255 byte limit does not apply to arguments to utility which do not contain 
     replstr, and furthermore, no replacement will be done on utility itself. Implies -x. 

-J replstr 
     If this option is specified, xargs will use the data read from standard input to replace the first occur- 
     rence of replstr instead of appending that data after all other arguments. This option will not affect 
     how many arguments will be read from input (-n), or the size of the command(s) xargs will generate (-s). 
     The option just moves where those arguments will be placed in the command(s) that are executed. The 
     replstr must show up as a distinct argument to xargs. It will not be recognized if, for instance, it is 
     in the middle of a quoted string. Furthermore, only the first occurrence of the replstr will be 
     replaced. For example, the following command will copy the list of files and directories which start 
     with an uppercase letter in the current directory to destdir: 

       /bin/ls -1d [A-Z]* | xargs -J % cp -rp % destdir 
+0

これは本当にセクシーです – jh314

+0

これは ' -o -path "$ dir/archive crl cfg" -prune' – musiphil

+0

@musiphil正確にコピーしてwitg bashを実行してください私の回答に書かれている内容を正確に表示してください今すぐダブルチェックしてください – jm666

2

を引用された形の各変数を常に扱うように努めます(例:手動でエスケープしても完璧ではないため、引用符を自分で挿入するのではなく(SQLで入力をエスケープするのではなく、パラメータ化された文を使用する必要があります)たとえば、変数に引用符が含まれているとします。

この点に関して、findの各引数ワードが("-o" "-path" "$dir/archive" "-prune" "-o" "-path" "$dir/crl" "-prune" "-o" "-path" "$dir/cfg" "-prune")(12要素配列)になる配列を作成することを目指します。

残念ながら、Bashは、各要素が複数の単語に展開されるようなパラメータ拡張の形式をサポートしていないようです。 (p{1,2,3}qp1q p2q p3qに展開、しかしa=(1 2 3)で、p"${a[@]}"qp1 2 3qに展開されます。)だから、ループに頼る必要があります。

printf -- '-o -path "$dir/%s" -prune ' ${ignore[@]}

declare -a args=() 
for i in "${ignore[@]}" 
do 
    args+=(-o -path "$dir/$i" -prune) # I'm not sure if you want to have 
             # $dir expanded at this point; 
             # otherwise, just use "\$dir/$i". 
done 

find ... "${args[@]}" ... 
1

も同様に仕事をしていませんprintfを見て、持っています

関連する問題