次のようにコマンドします:
find /directory -type f -name "*.txt" -print | xargs rm
ディレクトリとサブディレクトリ内のすべての.txt
ファイルを削除すれば問題ありません。しかし、ファイル拡張子用の変数または配列を作成し、find
例えば、
TXT=(*.txt)
for ii in ${TXT[@]}; do
find /directory -type f -name $TXT -print | xargs rm
done
このコマンドはサブディレクトリ内のファイルを削除しません.txt
。なぜでしょうか? この 2 番目のコードを変更してサブディレクトリ内のファイルを削除するにはどうすればよいでしょうか?
PS: ファイル拡張子が複数あるため、配列を使用しました。
答え1
配列の割り当て、
TXT=(*.txt)
は、パターンを、そのパターンに一致する現在のディレクトリ内のファイル名のリストに展開します*.txt
。シェルは割り当て時にこれを実行します。これは必要なことではありません。次のようにfind
リテラル文字列を指定する必要があります。*.txt
pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +
ここでは、 も削除しxargs rm
、代わりにrm
から直接実行していますfind
。 の現在の実装のほとんどは、の代わりにfind
非標準 を使用できます。-delete
-exec rm {} +
pattern='*.txt'
find /directory -type f -name "$pattern" -delete
ここでは 1 つのパターンのみを扱っているため、ループは不要であることに注意してください。また、 の"$pattern"
呼び出しでを引用符で囲むことfind
が重要であることにも注意してください。そうしないと、パターンは開始前に現在のディレクトリにある一致するすべてのファイル名に置き換えられますfind
。
いくつかのパターンについては、次のようにループを実行できます。
patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
find /directory -type f -name "$pattern" -delete
done
配列の割り当てにおける引用符は、シェルがパターンをファイル名のグロブ パターンとして使用するのを防ぐため重要です。 および の引用符"${patterns[@]}"
も"$pattern"
同様に、同じ理由で重要です。
もう 1 つの方法は、複数のパターンがある場合でも、 を 1 回だけ呼び出すことですfind
。 が大規模なディレクトリ階層である場合、この方法により処理速度が大幅に向上します。次のコードでは、 が使用するテスト/directory
の配列を構築することでこれを実現します。-name
find
patterns=( '*.txt' '*.tmp' )
name_tests=( )
for pattern in "${patterns[@]}"; do
name_tests+=( -o -name "$pattern" )
done
# "${name_tests[@]:1}" removes the initial "-o", which shouldn't be there.
name_tests=( '(' "${name_tests[@]:1}" ')' )
find /directory -type f "${name_tests[@]}" -delete
上記のスクリプトでは、最後に実行される実際のコマンドは次のようになります。
find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete
...ファイル名のサフィックスを持つすべての通常ファイルを削除します.txt
または .tmp
ディレクトリ内またはディレクトリ以下の任意の場所/directory
。