
次のファイルが提供されます。
data/A/a.txt
data/B/b.pdf
...
date/P/whatever.log
...
data/Z/z.jpg
data/A/
、、data/B/
...data/Z/
ディレクトリ内のすべてのファイルを削除したいと思います。とは別にファイルにリストされているディレクトリの1つの下にあるファイルdata/dont_clean.txt
。たとえば、リストした場合、data/P
以下data/dont_clean.txt
には何も触れないでくださいdata/P/
。
それは次のとおりです。
find data/ -mindepth 2 -maxdepth 2 -type f -not -path {listed in data/dont_clean} -delete
もちろん、これは有効なコマンドではありません。
私が試したバリエーション
find data/ -mindepth 2 -maxdepth 2 -type f -exec grep data/dont_clean.txt '{}' \;
しかし、ちょうど間違ったコマンドを生成したのか、私が実行した出力を得たのかわかりません。
Ubuntu 12.10でbashを使用しています
答え1
以下は大まかにテストしたコードですが、方法を教えてもらうことができます。次のファイルがあるとしますignore.txt
。
1/
2/
サンプル
次のファイルを含むサンプルディレクトリがあります。
$ mkdir -p dirs/{1..5}
$ touch dirs/{1..5}/afile
結果は次のとおりです。
$ tree dirs/
dirs/
|-- 1
| `-- afile
|-- 2
| `-- afile
|-- 3
| `-- afile
|-- 4
| `-- afile
`-- 5
`-- afile
実行例
このツリーに対してこのコマンドを実行すると、次のようになります。
$ find dirs/ -type f -print0 | fgrep -zFvf ./ignore.txt
dirs/5/afiledirs/4/afiledirs/3/afile
にリストされていないディレクトリのファイルだけがインポートされていることがわかりますignore.txt
。
したがって、rm
除外されていないファイルを削除するために最後に1つを追加できます。
$ find dirs/ -type f -print0 | fgrep -zFvf ./ignore.txt | xargs -0 rm -f
調べてみるとうまくいくのがわかります。
$ tree dirs/
dirs/
|-- 1
| `-- afile
|-- 2
| `-- afile
|-- 3
|-- 4
`-- 5
解決が必要な問題
このアプローチの大きな問題は、ファイル内の文字列がignore.txt
ディレクトリ構造の他の部分と一致する可能性があることです。したがって、このファイルの文字列が期待どおりに一意であることを確認するために注意を払う必要があります。
ロープの周りにいくつかのバリアを配置することで、ロープを保護するためにロープの最初または最後に固定できます。
詳細
上記のコマンドは次のことを行います。
- ディレクトリ内のすべてのファイルを探す
dirs
igonre.txt
ファイルが存在するディレクトリ内のすべてのファイルをフィルタリングします。- フィルタリストをコマンド
xargs
に渡すrm -f
答え2
そのコマンドの例のようですcomm
。
list of files to not delete in "keeper"
ls >current
comm -23 current ../keeper | more
リストが正しいことを確認してください
comm -23 current ../keeper | xargs rm
答え3
xargs
そしてfind
組み合わせ
デモ:
私のファイル:
[root@mail tmp]# find data/ -type f
data/A/d.txt
data/A/b.txt
data/A/a.txt
data/A/c.txt
data/B/e.txt
data/B/g.txt
data/B/f.txt
data/B/i.txt
除外リスト
[root@mail tmp]# cat exclude
data/A/a.txt
data/B/e.txt
xargsを使用して検索
[root@mail tmp]# find data/ -type f $( xargs -I{} echo -n " -not -path {} " < exclude )
data/A/d.txt
data/A/b.txt
data/A/c.txt
data/B/g.txt
data/B/f.txt
data/B/i.txt
出力が大丈夫だと思うので削除してみましょう。しかし、その前に次のコマンドの出力が正しいことを確認してから、2番目の最後のecho
コマンドを削除できます。
[root@mail tmp]# find data/ -type f $( xargs -I{} echo -n " -not -path {} " < exclude ) | xargs -n1 echo rm -rf
rm -rf data/A/d.txt
rm -rf data/A/b.txt
rm -rf data/A/c.txt
rm -rf data/B/g.txt
rm -rf data/B/f.txt
rm -rf data/B/i.txt
答え4
これは2つのステップで実行できます。タグを付けて(ユニークにするために)、保護されていないコンテンツを削除することです。
これらのファイルがすべて同じユーザーのものである場合は、このリストを使用して所有権またはグループを別のユーザーに変更できます。次に find を使用して残りを削除し、ユーザーを再変更します。すべてのファイルに同じ読み取り権限がある場合(再度切り替える方法がわかっている場合)、ユーザーを変更するよりもはるかに簡単なので(root権限が不要)、読み取り権限を削除(表示)できます。
while read file; do chmod u-w -R "$file"; done < "data/dont_clean.txt"
find data/ -mindepth 2 -maxdepth 2 -type f -writable -delete
while read file; do chmod u+w -R "$file"; done < "data/dont_clean.txt"
ディレクトリ全体を保護するには、編集(再帰を追加)してください。 chmodの再帰の問題を回避するには、権限を読み取りから書き込みに変更します(変更したばかりのディレクトリを読み取れません)。