変数内のファイル名パターンを使用して xargs rm を検索します

変数内のファイル名パターンを使用して xargs rm を検索します

次のようにコマンドします:

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の配列を構築することでこれを実現します。-namefind

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

関連情報