假设我有一个简单的愚蠢脚本,通过结束来删除文件,如下所示:
rm *.uvw *.xyz
rm
准确地说,如果脚本找不到至少一个具有指定结尾的文件,则它会在 stderr 上写入消息。
现在假设脚本更大一点,并且用更多的文件类型做更多的事情,我对哪些文件类型存在和哪些不感兴趣不感兴趣,但是对不存在的文件类型的抱怨阻碍了其余的工作我更感兴趣的输出和错误消息,所以我想过滤输出:
rm *.uvw *.xyz 2>&1 | grep -v "No such file or directory"
这在大多数情况下都可以正常工作,但它删除了交互式对话框的消息部分,例如询问是否应删除写保护的文件,因此我会收到提示而没有相应的消息。
我不理解这种行为,也找不到任何相关信息。有人可以解释一下吗?
答案1
问题
当 rm 提示使用输入时,它不会在提示末尾添加换行符:
$ rm *.uvw *.xyz
rm: remove write-protected regular empty file 'a.xyz'?
grep
是基于线路的。它只能处理完整的线路。在该行完成之前,它无法判断是否应该打印该行。因此,用于处理缓冲的标准实用程序(例如stdbuf
)无济于事。
解决方案
使用 nullglob 并删除丢失文件消息。
如果没有 nullglob,则会出现您不希望出现的消息:
$ rm *.uvw *.xyz
rm: cannot remove '*.uvw': No such file or directory
rm: remove write-protected regular empty file 'a.xyz'? n
有了它,“没有这样的文件或目录”消息就被抑制了:
$ shopt -s nullglob
$ rm *.uvw *.xyz
rm: remove write-protected regular empty file 'a.xyz'? n
细化
如果根本没有与任一 glob 匹配的文件,则会出现不同的错误消息:
$ shopt -s nullglob
$ rm *.uvw *.xyz
rm: missing operand
Try 'rm --help' for more information.
避免这种情况的一种简单方法是确保至少存在一个这样的文件:
shopt -s nullglob
[ -e "deleteme.xyz" ] ||touch deleteme.xyz
rm *.uvw *.xyz
既然deleteme.xyz
无论如何都会被抹掉,所以在跑之前碰一下它也没什么坏处rm
。
答案2
如果您使用 GNU grep,请查看“-s”选项来抑制消息。
-s, --no-messages
Suppress error messages about nonexistent or unreadable files.
*** 注意:这不是一个便携式选项。