
ディレクトリとそのサブディレクトリ内のすべての txt、xls、pdf ファイルを削除したいと思います。その他はすべて保存したいと思います。
find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete
それは実行されたように見えますが、必要な他のファイルがいくつか削除されました。他のものを削除せずにこれを実現するにはどうすればよいでしょうか?
答え1
代わりに次の操作を行ってください:
find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
正規表現を使用することもできます:
find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete
答え2
find を使用してこの問題に取り組む方法は基本的に 4 つあります。
方法1 - 使用-delete
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
このQ&Aで他の人が言っているように、この方法は最も速く、リソースをあまり消費しません。オンラインドキュメントを探す:
10.1.6 `-delete'アクションの使用
この問題を解決する最も効率的かつ安全な方法は、`-delete' アクションを使用することです。
find /var/tmp/stuff -mtime +90 -delete
この代替手段は、新しいプロセスをフォークして/bin/rm
-exec' or
を使用するオーバーヘッドを完全に回避するため、どの -execdir アクションよりも効率的です。また、通常は-delete アクションよりも効率的であり、`-execdir' アクションと同じセキュリティ上の利点があります。exec' to run
xargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the
「-delete」アクションは、BSD ファミリのオペレーティング システムによって導入されました。
注記:このアプローチで覚えておくべきことの 1 つは、 の使用は-delete
スイッチ も意味することです-depth
。これはどういう意味でしょうか? 以下は、-delete
注意しないと失敗する可能性がある例です。
たとえば、Subversion 作業ディレクトリがあり、一部のファイルをクリーンアップしたいが、.svn サブディレクトリはそのまま残したいとします。これを実現するには、次のコマンドを使用します。
$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt
ただし、スイッチ-delete
が含まれているため-depth
、実際に処理されるファイルは次のようになります。
$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt
このため、 を使用する場合は-delete
注意が必要です。
方法2 --exec command {} +
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+
方法と比較すると-delete
、これはパフォーマンスと Unix 間の移植性の点で、おそらく次善の選択肢です。-exec ... {} +
表記法は次のように機能します。
findのmanページより
-exec アクションのこのバリエーションは、選択されたファイルに対して指定されたコマンドを実行しますが、コマンド ラインは、選択された各ファイル名を末尾に追加することによって構築されます。コマンドの呼び出しの合計数は、一致したファイルの数よりもはるかに少なくなります。コマンド ラインは、xargs がコマンド ラインを構築するのとほぼ同じ方法で構築されます。コマンド内では、`{}' のインスタンスは 1 つだけ使用できます。コマンドは開始ディレクトリで実行されます。
したがって、実際には、このメソッドは と同様に動作しますxargs
が、 find の出力をパイプ経由で に渡すという面倒な手順を踏む必要はありませんxargs
。
方法3 -xargs
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f
はfind ... -print0
、指定された基準に一致するファイルのリストを作成します。このリストは、パイプを介して に渡されますxargs
。-print0
スイッチは、find からの各結果の間に区切り文字として ASCII NUL 文字を挿入します。-0
スイッチをオンにするxargs
と、渡されるファイルは ASCII NUL 文字で区切られているものとみなされます。
方法 1 および 2 と比較すると、この方法は方法 2 と同様のパフォーマンスが得られますが、この-print0
スイッチはすべての Unix で普遍的にサポートされているわけではありません。
方法4 --exec command {} \;
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;
最初の 3 つの方法と比較すると、これは最もパフォーマンスが低くなります。コマンドが検出したrm
個々のファイルごとにコマンドを文字通り呼び出しますfind
。
セキュリティに関する追加の考慮事項
上記の方法のいずれかを使用するときに、あまり明らかではないかもしれないことの 1 つは、一部の方法が他の方法よりも安全であるということです。おそらく、自分自身に「... セキュリティ? ... 何?」と言っているでしょう。次に例を示します。
ルートユーザーとして、次のコマンドを実行します。
$ find /var/tmp/somedir -type f -exec rm {} \;
/etc
知らないうちに、誰かがの下のディレクトリへのリンクを悪意を持って作成しています/var/tmp/somedir
。上記のコマンドを実行すると、ディレクトリ/etc
も削除されます。この問題は、オプション (方法 #1) を除く、ファイルを削除するすべての方法で発生します-delete
。
要約:
find を利用してファイルを削除する最も高速かつ安全な方法は を使用することです-delete
。 を使用するxargs -0
とパフォーマンスは同様ですが、安全性は劣ります。 この-delete
アクションは完全には移植可能ではありません。 最も効率的な移植可能な代替手段は です-exec ... +
が、これは安全ではなく、4.2.12 より前のバージョンの GNU findutils ではサポートされていません。
参考文献
答え3
若干の不正確さがあるslmの回答。
注意事項と免責事項: これはコメントする必要がありますslmの回答しかし、今はまだコメントできません。
「誰かが悪意を持ってリンクを作成した」という例は、セキュリティに関する追加の考慮事項Unix ハード リンクと Unix ソフト リンクの両方について完全に正確ではありません。
両者の違いを理解するには、Unix のハードリンクとシンボリックリンクまたはグーグルで検索してください。
ソフトリンク(とにかく最もよく使われるタイプ)の場合GNU find
、BDS find
ではない-L
シンボリックリンクの追跡を強制する特定のフラグが使用されない限り、シンボリックリンクをたどります。[参照man find
]
したがって、この例は、あなたが力 find
フラグを使用してソフトリンクをたどる-L
。いずれにしても、これは危険な選択です。
ハードリンクの場合はfind
、別のファイルただし、ハードリンクは別のディレクトリman ln
GNU の場合、「おそらく失敗する」ln
:
-d, -F, --directory
allow the superuser to attempt to hard link directories (note: will probably
fail due to system restrictions, even for the superuser)
したがって、ディレクトリへのハードリンクを最初から作成することはおそらく不可能であり、find
従うべきものは何もありません。
一部の BDSln
実装には-d
オプションがまったくないことに注意してください。