删除目录中的所有文件,除了文件中列出的路径的文件

删除目录中的所有文件,除了文件中列出的路径的文件

给定以下文件:

data/A/a.txt
data/B/b.pdf
...
date/P/whatever.log
...
data/Z/z.jpg

我想删除data/A/, data/B/, ...,data/Z/目录中的所有文件除了位于文件中列出的目录之一下的那些文件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在末尾添加一个来删除非排除的文件。

$ 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. 将过滤器列表传递xargsrm -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

xargsfind组合

演示:

我的文件 :

[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

看起来输出正常,让删除,但在此之前确保以下命令的输出正常,然后您可以删除倒数第二个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

您可以分两步完成:标记(使它们与众不同),然后删除不受保护的内容。

如果所有这些文件都来自同一用户,则您可以使用该列表将所有权或组更改为另一个用户。然后使用 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 递归问题(它无法读取刚刚更改的目录)。

相关内容