Contents

删除目录中的所有文件(某些文件除外)

1. 概述

在 Bash 终端中删除文件可能是一项艰巨的任务,尤其是当我们不确定如何定位文件时。出于同样的原因,通常最好删除每个目录的文件,而不是跨多个子目录删除它们,除非我们完全确定我们的操作。

在本教程中,让我们看看三种删除目录中所有文件的好方法,除了我们仍然需要的文件。

2. 使用find命令

使用find ,我们可以使用*-not等选项来帮助指示不应删除哪些文件,并使用-delete*选项来删除目录中的其余文件:

find [path to directory] -type f -not -name [filename or extension] -delete

例如,让我们看看如何删除测试目录中除file1.jpgfile2.pngfile3.pdffile4.zip之外的所有文件:

$ ls
'file1 (another copy).jpg'  'file3 (another copy).pdf'
'file1 (copy).jpg'          'file3 (copy).pdf'
 file1.jpg                   file3.pdf
'file2 (another copy).png'  'file4 (another copy).zip'
'file2 (copy).png'          'file4 (copy).zip'
 file2.png                   file4.zip
$find . -type f -not \( -name 'file1.jpg' -or -name 'file2.png' -or -name 'file3.pdf' -or -name 'file4.zip' \) -delete

接下来,我们列出测试目录的内容:

$ ls
file1.jpg  file2.png  file3.pdf  file4.zip

我们使用上面的find命令排除的文件仍然包含在目录中。

3. 使用扩展通配符和模式匹配运算符

扩展通配符也称为extglob 。启用extglob时,它会激活可用于增强rm 命令有效性的模式匹配运算符。此外,与*!运算符,我们可以在删除期间排除我们不希望glob*匹配的所有文件。

让我们看一下模式匹配运算符的列表:

  • *?(pattern-list)*匹配至少零次且最多一次出现
  • **(pattern-list)*匹配零次、一次或多次出现
  • *+(pattern-list)*匹配一个或多个匹配项
  • *@(pattern-list)*匹配一个模式出现
  • *!(pattern-list)*从匹配中排除给定的模式

要为给定的 Bash 会话启用extglob ,我们可以使用内置的shopt

$ shopt -s extglob

在此之后,要排除文件,我们使用! 运营商**:

$ rm -v !("[file]")

让我们刷新测试目录file1.jpgfile2.pngfile3.pdffile4.zip的内容:

$ ls
'file1 (3rd copy).jpg'      'file3 (3rd copy).pdf'
'file1 (another copy).jpg'  'file3 (another copy).pdf'
'file1 (copy).jpg'          'file3 (copy).pdf'
 file1.jpg                   file3.pdf
'file2 (3rd copy).png'      'file4 (3rd copy).zip'
'file2 (another copy).png'  'file4 (another copy).zip'
'file2 (copy).png'          'file4 (copy).zip'
 file2.png                   file4.zip

要从删除中排除多个文件或文件扩展名,我们使用| ,也称为管道,将它们分开:**

$ rm -v !("file1.jpg"|"file2.png"|"file3.pdf"|"file4.zip")
removed 'file1 (3rd copy).jpg'
removed 'file1 (another copy).jpg'
removed 'file1 (copy).jpg'
removed 'file2 (3rd copy).png'
removed 'file2 (another copy).png'
removed 'file2 (copy).png'
removed 'file3 (3rd copy).pdf'
removed 'file3 (another copy).pdf'
removed 'file3 (copy).pdf'
removed 'file4 (3rd copy).zip'
removed 'file4 (another copy).zip'
removed 'file4 (copy).zip'

但是,当不使用扩展通配符时,通常最好禁用它:

$ shopt -u extglob

最后,我们可以使用extglob来排除使用文件类型的文件,例如*.png*:

 $ rm !(*.png)

因此,上面的代码片段会删除目录中的所有文件,但*.png*文件类型的文件除外。

4. 使用 Bash GLOBIGNORE变量

** GLOBIGNORE指定glob不应匹配**的数据或模式。

让我们用我们想从删除中排除的文件设置GLOBIGNORE变量。

$ GLOBIGNORE=file1.jpg:file2.png:file3.pdf:file4.zip

使用与上一节中的目录结构等效的目录结构,以下命令将删除除GLOBIGNORE变量中设置的文件之外的所有文件:

$ rm -v *
removed 'file1 (3rd copy).jpg'
removed 'file1 (another copy).jpg'
removed 'file1 (copy).jpg'
removed 'file2 (3rd copy).png'
removed 'file2 (another copy).png'
removed 'file2 (copy).png'
removed 'file3 (3rd copy).pdf'
removed 'file3 (another copy).pdf'
removed 'file3 (copy).pdf'
removed 'file4 (3rd copy).zip'
removed 'file4 (another copy).zip'
removed 'file4 (copy).zip'

最重要的是,我们可以取消设置GLOBIGNORE$ unset GLOBIGNORE 这是一个很好的做法,因为GLOBIGNORE将指定的文件从模式匹配中排除。反过来,当不知道排除项时,我们运行的命令可能不会影响所有文件,这可能令人沮丧且难以解决。

但是,当我们设置GLOBIGNORE时,我们使用了 Bash 特定的功能。因此,从所有模式匹配中会自动排除. 和*..*。**