Unix - 删除不包括 PATTERN 的文件和文件夹

jox*_*oxl 10 unix command-line

最近我面临着删除目录中所有文件/文件夹的任务,不包括那些匹配特定模式的文件/文件夹。所以我编写了一个单行 unix 命令来完成这项工作。必须只有一行吗?我想不是,但那样肯定更酷!

虽然问题很简单,但我对我的解决方案最终变得如此复杂感到有些惊讶。这是我使用的命令;注意:这是一个糟糕的解决方案,因为它不处理包含换行符的文件名(这在我的情况下无关紧要)。

ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Run Code Online (Sandbox Code Playgroud)

我没有使用“find”命令,因为我不想递归到匹配 PATTERN 的文件夹中。例如,考虑以下文件结构:

file_foo.txt
first_dir
  |
  +--> contents
  +--> ...
foo_dir
  |
  +--> anotherfile.txt
  +--> morefiles.log
foo_file.txt
somefile.txt
Run Code Online (Sandbox Code Playgroud)

使用模式“foo”必须只删除“first_dir”(当然也是它的内容)和“somefile.txt”(不是“anotherfile.txt”或“morefiles.log”)。

问题,是否有更好(更优雅和正确)的方法来实现这一目标?


编辑:
最近我注意到“查找”可能是一个更好的选择:

find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Run Code Online (Sandbox Code Playgroud)

此解决方案可以正确处理包含换行符的路径。

Chr*_*sen 10

以下示例带有echo前缀,以便您可以在实际使用模式之前对其进行测试。删除echo以激活rm -rf。代替rm -ri提示进行确认。

ksh对其 globbing 有一个否定匹配扩展:

# ksh
echo rm -rf !(*foo*)
Run Code Online (Sandbox Code Playgroud)

如果你设置了这个选项,同样的语法在bash 中是可用的extglob

# bash
shopt -s extglob
echo rm -rf !(*foo*)
Run Code Online (Sandbox Code Playgroud)

zsh对此有自己的语法:

# zsh
setopt extended_glob
echo rm -rf ^*foo*
Run Code Online (Sandbox Code Playgroud)

它还可以使用ksh风格的语法:

# zsh: ksh-style glob syntax
setopt ksh_glob no_bare_glob_qual
echo rm -rf !(*foo*)

# zsh: ksh-style glob syntax, adapted for the default bare_glob_qual option
setopt ksh_glob bare_glob_qual
echo rm -rf (!(*foo*))
Run Code Online (Sandbox Code Playgroud)


gar*_*ohn 7

这是另一个find解决方案。我不确定这比你的有什么真正的优势,但它不需要xargs并允许 * 扩展到太多名称的罕见可能性。

find . -maxdepth 1 ! -name PATTERN -type f -delete
Run Code Online (Sandbox Code Playgroud)

我还添加了-type f这样它就不会尝试删除目录。

警告:-delete功能强大。我给了我的一个测试文件 0 权限,上面的命令毫不犹豫地删除了它。

  • 先测试。将 `-delete` 替换为 `-print` 以查看它是否找到了您想要的文件。如果一切正常,请使用命令历史记录(例如按向上按钮)返回上一个命令,以确保您使用相同的查找过滤器。 (6认同)