![查找并删除文件,同时保留特定目录中的所有匹配文件](https://linux22.com/image/129241/%E6%9F%A5%E6%89%BE%E5%B9%B6%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%EF%BC%8C%E5%90%8C%E6%97%B6%E4%BF%9D%E7%95%99%E7%89%B9%E5%AE%9A%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%8C%B9%E9%85%8D%E6%96%87%E4%BB%B6.png)
我有一个有趣的问题,这个问题可能很容易,也可能不容易:(我一直在尝试找出一种方法来集成 Linux 上“find”命令的选项。
基本上,我有一个目录树,其中可能有多个需要保留或删除的文件示例。为了论证 .XX,所有文件共享相同的扩展名(尽管我们的想法是尽可能通用,因此它可以是任何文件)。我想删除目录树中的所有 .XX 文件,除了文件位于特定文件夹中的位置(将始终具有相同的标题,在示例中称为 YYY)。
假设我必须遵循以下结构(其中每个子目录最终可能包含许多我不想触摸或影响的文件以及我所做的文件):
folder_root:
|
|--> Subdir_1/interesting_file_1.XX
|--> Subdir_1/interesting_file_2.XX
|--> Subdir_1/unrelated_interesting_file_1.AA
|--> Subdir_2
|--> Subdir_3/interesting_file_3.XX
|--> YYY/interesting_file_4.XX
|--> YYY//interesting_file_5.XX
我想留下:
folder_root:
|
|--> Subdir_1/unrelated_interesting_file_1.AA
|--> YYY/interesting_file_4.XX
|--> YYY/interesting_file_5.XX
请注意,目录 YYY 可以在任何地方,并且可能有很多目录,因此不可能拥有需要手动排除的目录路径列表来构建大型排除列表。
首先,我做了一个基本的Find
工作find . -iname "*.XX"
:然后我考虑添加-printf "%h\n"
以输出包含 .XX 文件的目录。我正在努力做的是获取输出的列表,并用它来通知删除或不删除的过程(视情况而定)。我想我可以用来grep
将输出中的任何 YYY 文件夹删除到临时文件中,使用循环while read
,然后使用pushd
和popd
移入文件夹,然后移出文件夹,find . -iname "*.XX" -delete
在每个子目录中使用一个简单的方法(然后使用-empty
find 中的开关)清理由此留下的任何空目录)。然而,这确实感觉非常钝,用一个非常大的大锤,这可能是系统密集型的,特别是在处理潜在的数百个子目录时。
我很感兴趣是否有一种“更好”的方法,即更灵活,总体上不太密集且可靠(特别是如果您最终必须针对三到四种不同的文件类型运行三到四次)?
可能没有,但值得快速询问:)当一个简单的锤子就可以的时候为什么要使用大锤!? :)
最后注意,我无法向系统添加额外的 shell 命令(并且使用的系统是 Ubuntu 和 Centos 的混合),因此在可能的情况下,需要使用预先存在的命令集(假设除了 Tree 之外没有安装其他模块) ,我确实知道)。我希望这个问题很清楚,并且足够“通用”,如果找到简单的答案,足以对其处于不同情况的其他人有用。
答案1
我认为您不需要 Pushd Popd 等,因为 find 会生成完整路径名。
如果文件名包含回车符后跟星号,则任何 readline 方法都会产生有趣的结果。
一般的解决方案是使用 find 生成所有候选者的空终止列表,使用 grep winnow,使用 xargs 执行:
find . -iname "*.XX" -print0 | grep -vzf keep_these.txt | xargs -0 echo rm -- # remove the echo to ACTUALLY delete files
“keep_these.txt”是要排除的目录列表,每行一个,包括前导斜杠和尾随斜杠,例如:
/YYY/
/I love this directory/
如果您不需要正则表达式来识别您的目录(只需固定字符串),请添加-F
到 grep.
答案2
这应该有效:
find folder_root/ -name Subdir_2 -prune -o -name Subdir_3 -prune -a -type f
如果找到正确的文件集,您可以添加-delete
到命令的末尾find
。