rm 命令与 xargs 一起使用以排除名称中具有 space 的某些文件夹

rm command to be use with xargs to exclude some folders having space in the name

在一个目录中,我有大约 50 个文件和文件夹,其中包括一些名称中带有 space 的文件夹。我想使用 ls、grep 和 xargs 命令删除一些文件夹,但无法删除名称中带有 space 的文件夹并显示异常。谁能帮忙?使用 Solaris OS。 我在下面尝试删除除 $files

之外的所有内容

ls | grep -v "$文件" | xargs rm

当我尝试下面的命令时,它删除了所有内容,包括我不想要的 $files。

ls | grep -v "$文件" | xargs rm --*\ *

类 Unix 系统允许任何字符出现在文件名中,但 ASCII NUL 字符和斜杠除外。斜杠可以出现在路径名中(作为目录分隔符),但不能出现在实际目录条目的名称中。这意味着 xargs 读取的文件列表实际上可能包含白色 space 字符 – space、制表符和换行符。由于默认情况下,xargs 假定它正在读取的文件列表使用白色 space 作为参数分隔符,因此它无法正确处理文件名实际包含白色 space 的情况。这使得 xargs 的默认行为几乎无法处理任意数据。

为了解决这个问题,GNU findutils 为查找引入了“-print0”操作。这使用 ASCII NUL 字符来分隔它生成的文件列表中的条目。这是分隔符的理想选择,因为它是唯一不能出现在路径名中的字符。 xargs 的“-0”选项使其假定参数用 ASCII NUL 分隔而不是白色 space。它还关闭了 xargs 默认行为中的另一个错误功能,即它会注意输入中的引号字符。 xargs 的某些版本在输入中看到单独的“_”时也会终止,但 GNU find 不再这样做(因为它已成为 Unix 标准中的可选行为)。

所以,将 find -print0 与 xargs -0 放在一起,我们得到这个命令:

find /var/tmp/stuff -mtime +90 -print0 | xargs -0 /bin/rm

结果是一种有效的处理方式,可以正确处理所有可能出现在要删除的文件列表中的字符。这是个好消息。然而,正如我相信您所预料的那样,还有更多的坏消息。问题是这不是一个可移植的结构;尽管其他版本的 Unix(尤其是 BSD 派生的)支持“-print0”,但它并不通用。

除非使用 -r 选项(递归),否则无法使用 rm 命令删除文件夹。我假设你想删除单个文件,而不是整个目录。

在任何情况下,您都可以使用 Solaris 始终可用的标准 find 命令处理具有任意名称的文件和目录。 xargs 和 GNU 特定扩展都不是必需的。

这是一个例子。除了后缀为 .jpg 或 .java 的文件,以及名称中包含 keepme 的文件将被保留,所有剩余文件将被处理:

find . -type f ! -name "*.jpg" ! -name "*keepme*" ! -name "*.java" -exec echo rm {} +

如果您希望实际执行文件删除,请删除 echo 命令。

在不使用非标准扩展的情况下,假设您的 shell 实现了 while read ...,这也应该有效:

ls | grep -v "$files" | while read filename; do
    rm "$filename"
done

$filename 周围的引号很重要。如果没有引号,参数将根据名称中可能存在的任何空格进行拆分。

另请注意,这不会删除目录 - 正如其他人提到的,您需要 rm -r - 或 rmdir - 才能执行此操作。但是 rm -r 将删除一个目录 以及其中的所有内容 rmdir 默认情况下不会删除非空目录。

您可能应该 运行 先用

之类的东西进行测试
ls | grep -v "$files" | while read filename; do
    ls -ld "$filename"
done

使用 -ld 选项到 ls 以确保您获得正确的文件,并且 列出目录内容如果文件传递的名称恰好是一个目录。