
免責事項:私はUnix / Linuxに初めて触れていますが、学ぶことを楽しみにしています!私はこのstackexchangeで検索を試して読みましたが、man find
これを理解できないようです。
find ... -exec {} +
このコマンドを使用して、特定のファイル拡張子を持つすべてのファイルを再帰的に見つけ、ファイルリストからコマンドを実行したいと思います。約100,000個のファイルを変換する必要があります。私が実行しているコマンドはファイル名(またはファイル名のリストなどf1 f2 f3
)を引数として受け入れますが、コマンドを実行するには追加の引数も指定する必要があります。
私が今まで試したこと:
これは働きます:
find . -iname "*.extension" -exec <command> {} <additional parameters> \;
これはうまくいかないようです:
find . -iname "*.extension" -exec <command> {} <additional parameters> +
エラーメッセージが表示されますfind: missing argument to '-exec'
。{}
?後に他のパラメータを指定できないと思います。
いくつかの注意:
-o <outputDir>
このコマンドは、ファイル名を最初のパラメータとして使用し、出力ディレクトリやファイルから抽出する変数など、いくつかの追加パラメータを指定する必要があります-v <var1,var2,...>
。
違いがある場合は、Ubuntu 12.04の端末でこれを実行しています。
答え1
find . -iname "*.extension" -exec sh -c '
exec <command> "$@" <additional parameters>' sh {} +
バラより"find...-exec sh -c '...' sh {}+" を使用した find コマンドはどのように機能しますか?もっと学ぶ。
答え2
これにより、1つのファイル名の代わりにスペースで区切られた複数のファイル名(ファイルが100,000個あるため長いリストになります)が一覧+
表示されます。{}
この場合、{}
コマンドの最後に表示する必要があります。
find(1)
以下のマニュアルページを参照してください-exec command {} +
。
答え3
すべてのディレクトリとファイルに共通の名前があると仮定すると(スペース、改行、または同様の文字が含まれていない)、これは膨大な数のファイルでも機能します。
find . -iname "*.extension" -exec sh -c '
command="<command>"
additionalParameters="<additional parameters>"
h=$(($#/2))
cmd="$command "
for i in $(seq 1 $h);do
cmd="$cmd $(eval echo \$$i) "
done
cmd="$cmd $additionalParameters"
$cmd
shift $h
$command "$@" $additionalParameters' sh {} +
理由:
句読点を使用する場合、+
find はコマンドをできるだけ大きくします。許容される最大パラメータ数(Gnu / Linuxでは128kでなければならない)とパラメータリストの最大サイズ(Gnu / Linuxでは2MBでなければならない)の2つの制限があります。問題は、呼び出されたコマンドに追加のパラメータ(追加のパラメータ)が必要であることです。これを追加すると制限が超過し、「パラメータが多すぎるエラー」が発生します。私が提案したスクリプトは、構築されたパラメータのリストを2つの部分に分割し、ブロックごとに1つではなく2つのコマンドを実行するため、追加のパラメータを追加することは問題になりません。
答え4
次のスクリプトを使用できます。
#! /bin/bash
cmd=echo
test $# -gt 2 || exit 2
num_trailing_args="$1"
[[ $num_trailing_args =~ ^(0|[1-9][0-9]*)$ ]] ||
{ echo "Illegal first argument ('${num_trailing_args}'); aborting"; exit 2; }
test $# -lt $((num_trailing_args+2)) &&
{ echo "Too few arguments; aborting"; exit 2; }
shift
trailing_args=()
for((i=0;i<num_trailing_args;i++)); do
trailing_args[i]="$1"
shift
done
"$cmd" "$@" "${trailing_args[@]}"
その後、使用
find ... -exec args_change_script.sh 3 t1 t2 t3 {} +
コマンド名はスクリプト名より長くしてはいけません(確かに言えば)。