如何删除文件夹中除list.txt中的名称文件之外的文件?

如何删除文件夹中除list.txt中的名称文件之外的文件?

假设文件夹中/photo有很多文件,例如

1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg

nodeletelist.txt我在此文本文件中有一个文件名,其名称为不删除文件列表,例如

1.jpg
2.jpg
3.jpg
nodeletelist.txt

如何删除文件:

4.jpg
...
10.jpg

除了文件1.jpg2.jpg3.jpg以及nodeletelist.txt哪个nodeletelist.txt

答案1

你有 GNU 发现吗?

find photo -mindepth 1 -maxdepth 1 -regextype awk \! -regex ".*/($(tr '\n' '|' < photo/nodeletelist.txt)nodeletelist.txt)" -delete

这是通过使用tr(1)和来实现的find(1)

  1. 将文件重定向到tr
  2. 用竖线替换换行符,表示“OR”
  3. 从子 shell 返回
  4. 在末尾添加一个标记值,以防文件以换行符结尾。 (在本例中,我使用您的名称nodeletelist.txt作为哨兵,因此如果您使用此解决方案,则不需要在文件中包含文件名。)
  5. 在目录中搜索正好位于下面一层的条目photo
  6. 使用 awk 正则表达式来匹配上面步骤 1-4 返回的字符串
  7. 删除文件不是由正则表达式匹配(因为!表示“NOT”)

此处的标志-regextype也可以设置为posix-extendedegrepposix-egrepgnu-awk或,posix-awk因为此处所需的扩展语法适用于它们。默认的 findutils 正则表达式、posix-basic、emacs、sed 等不适用于此命令。

答案2

如果zsh是一个选项,您可以定义一个 shell 函数来用作“全局限定符" 用于过滤 glob 中所有文件的列表*,例如

 % cmd() { ! grep -qF "$REPLY" ./nodeletelist.txt ; } 

然后(从photo/目录)

 % ls
 10.jpg   1.jpg   2.jpg   3.jpg   4.jpg   5.jpg   6.jpg   7.jpg   8.jpg   9.jpg   nodeletelist.txt
    
 % ls *(+cmd)                                         
10.jpg  4.jpg  5.jpg  6.jpg  7.jpg  8.jpg  9.jpg

看起来不错,我们删除吧

 % rm *(+cmd)

 % ls
1.jpg  2.jpg  3.jpg  nodeletelist.txt

可能有一种更有效的实现,首先将文件映射到数组中,然后测试是否$REPLY是数组的元素。

答案3

对我来说,最简单且易于记住,并且也适用于很多文件(思想会在文件名中的换行符处中断,但如果你有的话,你将不得不考虑你的列表):

cd /photo
ls -1 | grep -v -x -f nodeletelist.txt | xargs -d "\n" -P 0 rm -f

如果目录中有其他内容(子目录或不同的文件,我不假设您在列表中包含您的txt),我会使用 find I 而不是 ls (find . -maxdepth 1 -type f -name "*.jpg"例如)。

答案4

对于名称中没有空格的所述情况

rm $(join -v 1 <(ls *.jpg) <(sed '$ d' nodeletelist.txt))

假设文件nodeletelist.txt的最后一行实际读取nodeletelist.txt

如果没有,那么就

rm $(join -v 1 <(ls *.jpg) nodelete.txt)

但感觉不太优雅...

相关内容