次にリストされているパスのファイルを除いて、ディレクトリ内のすべてのファイルを削除します。

次にリストされているパスのファイルを除いて、ディレクトリ内のすべてのファイルを削除します。

次のファイルが提供されます。

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ディレクトリ構造の他の部分と一致する可能性があることです。したがって、このファイルの文字列が期待どおりに一意であることを確認するために注意を払う必要があります。

ロープの周りにいくつかのバリアを配置することで、ロープを保護するためにロープの最初または最後に固定できます。

詳細

上記のコマンドは次のことを行います。

  1. ディレクトリ内のすべてのファイルを探すdirs
  2. igonre.txtファイルが存在するディレクトリ内のすべてのファイルをフィルタリングします。
  3. フィルタリストをコマンド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の再帰の問題を回避するには、権限を読み取りから書き込みに変更します(変更したばかりのディレクトリを読み取れません)。

関連情報