我有一些失败的实验结果文件,它们的内容恰好是一个\n
(换行符)。
我想将它们全部列出(也许使用类似find
或 之类的东西grep
),以了解这些文件是什么,然后删除它们。
答案1
在搜索路径之外创建一个参考文件(它将.
在示例中):
echo >/tmp/reference
现在我们有一个与您要查找的文件相同的已知文件。然后将搜索路径(.
此处)下的所有常规文件与参考文件进行比较:
find . -type f -size 1c -exec cmp -s -- /tmp/reference {} \; -print
-size 1c
不是必须的,可以省略;只是为了提高性能。这是一个快速的初步测试,可以拒绝大小错误的文件,而不会产生额外的进程。cmp …
仅针对大小合适的文件创建相对昂贵的进程。
-s
让cmp
自己沉默。我们不需要它的输出,只需要退出状态。
--
解释如下:“--”(双破折号)是什么意思?在我们的示例中确实不需要它,即如果参考文件指定为/tmp/reference
并且搜索路径为.
.我用于防止有人不小心选择了否则会导致行为不当或失败的--
路径;cmp
有了--
它应该就可以了。
-exec
用作测试,当且仅当cmp
返回退出状态为零时,它才会成功;对于经过测试的文件,如果该文件与/tmp/reference
.这样,find
将为您提供与参考文件相同的文件的路径名。
该方法可用于查找任意固定内容的文件;您只需要一个包含确切内容的参考文件(-size …
如果您使用它,请不要忘记进行调整;-size "$(</tmp/reference wc -c)c"
会很方便)。在我们的特定情况下,echo
使用一个简单的方法来创建文件,因为它打印一个换行符,这正是您想要查找的内容。
要find
尝试删除每个匹配的文件,请使用-delete
(异-exec rm -- {} +
或)后-print
。
答案2
搜索单字节文件。将它们与已知值进行比较。如果匹配则打印和/或删除
find /path/to/files -type f -size 1c -exec sh -c 'printf "\n" | cmp -s -- - "$1"' _ {} \; -print
如果您想要静默运行,可以选择附加-delete
到删除,然后删除。-print
答案3
使用 GNU grep
,您可以-z
将整个文件视为单行(-z
使用grep
NUL 作为行终止符,因此只要您的文件实际上不包含 NUL,\0
它就具有将整个文件视为单个行的效果线)。如果我们将其与-l
仅打印文件名并-P
供 PCRE 使用\n
,我们可以搜索只有一个\n
而没有其他内容的“行”:
grep -lPz '^\n$' *
例如,给定这三个文件:
printf 'foo\n' > good_file_1
printf '\n\n\n\n' > good_file_2
printf '\n' > bad_file
运行grep
上面给出:
$ grep -lPz '^\n$' *
bad_file
globstar
您还可以使用 bash选项(来自 man )使其递归bash
:
环球星
如果设置,路径名扩展上下文中使用的模式 ** 将匹配所有文件以及零个或多个目录和子目录。如果模式后跟 /,则仅目录和子目录匹配。
例如,在这种情况下:
$ mkdir -p ./some/long/path/here/
$ cp bad_file some/long/path/here/bad_file_2
$ tree
.
├── bad_file
├── good_file_1
├── good_file_2
└── some
└── long
└── path
└── here
└── bad_file_2
5 directories, 4 files
启用globstar
并运行grep
将**/*
发现两个坏文件(我正在重定向标准错误,因为 grep 抱怨给出的目录而不是文件进行搜索;此类错误是预期的并且可以安全地忽略):
$ grep -lPz '^\n$' **/* 2>/dev/null
bad_file
some/long/path/here/bad_file_2
或者,find
仅用于搜索文件:
$ find . -type f -exec grep -lPz '^\n$' {} +
./some/long/path/here/bad_file_2
./bad_file
答案4
find . -size 1c -exec sh -c '[ -z "$(< $1)" ]' sh '{}' ';' -print
查找大小恰好为一个字节的文件,其中(在 shell 中)读取文件的结果为空—— sh 从命令替换中删除尾随换行符。