FxMySz Asked: 2024-01-05 02:26:59 +0800 CST2024-01-05 02:26:59 +0800 CST 2024-01-05 02:26:59 +0800 CST 如何递归列出全部内容恰好为“\n”的所有文件 772 我有一些失败的实验结果文件,它们的内容恰好是一个\n(换行符)。 我想将它们全部列出(也许使用类似find或 之类的东西grep),以了解这些文件是什么,然后删除它们。 bash 6 个回答 Voted Best Answer Kamil Maciorowski 2024-01-05T03:03:34+08:002024-01-05T03:03:34+08:00 在搜索路径之外创建一个参考文件(它将在.示例中): echo >/tmp/reference 现在我们有一个与您要查找的文件相同的已知文件。然后将搜索路径(.此处)下的所有常规文件与参考文件进行比较: find . -type f -size 1c -exec cmp -s -- /tmp/reference {} \; -print -size 1c不是必须的,可以省略;只是为了提高性能。这是一个快速的初步测试,可以拒绝大小错误的文件,而不会产生额外的进程。cmp …仅针对大小合适的文件创建相对昂贵的进程。 -scmp自己沉默了。我们不需要它的输出,只需要退出状态。 --此处解释:“--”(双破折号)是什么意思?在我们的示例中确实不需要它,即如果参考文件指定为/tmp/reference并且搜索路径为.. 我用于--防止有人不小心选择了否则会导致cmp行为不当或失败的路径;有了--它应该就可以了。 -exec用作测试,当且仅当cmp返回退出状态为零时,它才会成功;对于经过测试的文件,如果该文件与/tmp/reference. 这样,find将为您提供与参考文件相同的文件的路径名。 该方法可用于查找任意固定内容的文件;-size …您只需要一个包含确切内容的参考文件(如果您使用它,请不要忘记进行调整;-size "$(</tmp/reference wc -c)c"会很方便)。在我们的特定情况下,echo使用一个简单的方法来创建文件,因为它打印一个换行符,这正是您想要查找的内容。 要find尝试删除每个匹配的文件,请在 后使用-delete(xor -exec rm -- {} +)-print。 Chris Davies 2024-01-05T02:54:56+08:002024-01-05T02:54:56+08:00 搜索单字节文件。将它们与已知值进行比较。如果匹配则打印和/或删除 find /path/to/files -type f -size 1c -exec sh -c 'printf "\n" | cmp -s -- - "$1"' _ {} \; -print 如果您想要静默运行,可以选择附加-delete到删除,然后删除。-print terdon 2024-01-06T21:10:24+08:002024-01-06T21:10:24+08:00 使用 GNU grep,您可以将-z整个文件视为单行(-z使用grepNUL 作为行终止符,因此只要您的文件实际上不包含 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 Stéphane Chazelas 2024-01-05T17:24:17+08:002024-01-05T17:24:17+08:00 和zsh: zmodload zsh/mapfile print -rC1 -- **/*(ND.L1e[$' [[ $mapfile[$REPLY] = "\n" ]] ']) print -rC1:柱上print锯齿状_r1 C N: nullglob: 如果没有匹配,不要抱怨,而是传递一个空列表print。 D: dotglob: 不要跳过隐藏文件 .:仅限常规文件(例如-type finfind或file/ fin rawhide)。 L1:L长度1。 e[code]在文件上运行代码以进一步确定是否匹配 $mapfile[$REPLY]扩展到文件的内容(其路径位于 中$REPLY)。 POSIXly,并避免为每个文件生成一个或多个进程(假设sh其中read,[和printf是内置的实现,通常是这种情况): find . -type f -size 1c -exec sh -c ' for file do IFS= read -r line < "$file" && [ -z "$line" ] && printf "%s\n" "$file" done' sh {} + (请注意,与上面的 zsh 相反,该列表未排序)。 与rawhide(列表也未排序): rh -e 'file && size == 1 && " ".body' . 通过grep可以处理非文本文件(至少是 NUL 字节和非分隔行)的实现,例如grepC 语言环境中的 GNU,您还可以执行以下操作: LC_ALL=C find . -type f -size 1c -exec grep -l '^$' {} + glenn jackman 2024-01-05T02:55:42+08:002024-01-05T02:55:42+08:00 find . -size 1c -exec sh -c '[ -z "$(< $1)" ]' sh '{}' ';' -print 查找大小恰好为一个字节的文件,其中(在 shell 中)读取文件的结果为空—— sh 从命令替换中删除尾随换行符。 Jim L. 2024-01-05T03:29:22+08:002024-01-05T03:29:22+08:00 只是为了提供一种新颖的替代方案,在 FreeBSD 中,可以这样做: find . -maxdepth 1 -size 1c \ -exec md5 -q '--check=68b329da9893e34099c7d8ad5cb9c940 {} >/dev/null' \; -print 然而,md5 哈希值,即使是小文件,也可能比简单的cmp. 我尝试找到一种cmp使用bash的命令替换(和 BSD find)来表达该方法的方法,但它有点笨拙: find . -maxdepth 1 -size 1c -exec bash -c 'cmp -s "{}" <(echo)' \; -print 同样,多次创建换行文件可能比卡米尔创建一次参考文件并反复比较的方法稍微昂贵一些。
在搜索路径之外创建一个参考文件(它将在
.
示例中):现在我们有一个与您要查找的文件相同的已知文件。然后将搜索路径(
.
此处)下的所有常规文件与参考文件进行比较:-size 1c
不是必须的,可以省略;只是为了提高性能。这是一个快速的初步测试,可以拒绝大小错误的文件,而不会产生额外的进程。cmp …
仅针对大小合适的文件创建相对昂贵的进程。-s
cmp
自己沉默了。我们不需要它的输出,只需要退出状态。--
此处解释:“--”(双破折号)是什么意思?在我们的示例中确实不需要它,即如果参考文件指定为/tmp/reference
并且搜索路径为.
. 我用于--
防止有人不小心选择了否则会导致cmp
行为不当或失败的路径;有了--
它应该就可以了。-exec
用作测试,当且仅当cmp
返回退出状态为零时,它才会成功;对于经过测试的文件,如果该文件与/tmp/reference
. 这样,find
将为您提供与参考文件相同的文件的路径名。该方法可用于查找任意固定内容的文件;
-size …
您只需要一个包含确切内容的参考文件(如果您使用它,请不要忘记进行调整;-size "$(</tmp/reference wc -c)c"
会很方便)。在我们的特定情况下,echo
使用一个简单的方法来创建文件,因为它打印一个换行符,这正是您想要查找的内容。要
find
尝试删除每个匹配的文件,请在 后使用-delete
(xor-exec rm -- {} +
)-print
。搜索单字节文件。将它们与已知值进行比较。如果匹配则打印和/或删除
如果您想要静默运行,可以选择附加
-delete
到删除,然后删除。-print
使用 GNU
grep
,您可以将-z
整个文件视为单行(-z
使用grep
NUL 作为行终止符,因此只要您的文件实际上不包含 NUL,\0
它就具有将整个文件视为单个行的效果线)。如果我们将其与-l
仅打印文件名并-P
供 PCRE 使用\n
,我们可以搜索只有一个\n
而没有其他内容的“行”:例如,给定这三个文件:
运行
grep
上面给出:globstar
您还可以使用 bash选项(来自 man )使其递归bash
:例如,在这种情况下:
启用
globstar
并运行grep
将**/*
发现两个坏文件(我正在重定向标准错误,因为 grep 抱怨给出的目录而不是文件进行搜索;此类错误是预期的并且可以安全地忽略):或者,
find
仅用于搜索文件:和
zsh
:print -rC1
:柱上print
锯齿状_r
1
C
N
: nullglob: 如果没有匹配,不要抱怨,而是传递一个空列表print
。D
: dotglob: 不要跳过隐藏文件.
:仅限常规文件(例如-type f
infind
或file
/f
inrawhide
)。L1
:L
长度1
。e[code]
在文件上运行代码以进一步确定是否匹配$mapfile[$REPLY]
扩展到文件的内容(其路径位于 中$REPLY
)。POSIXly,并避免为每个文件生成一个或多个进程(假设
sh
其中read
,[
和printf
是内置的实现,通常是这种情况):(请注意,与上面的 zsh 相反,该列表未排序)。
与
rawhide
(列表也未排序):通过
grep
可以处理非文本文件(至少是 NUL 字节和非分隔行)的实现,例如grep
C 语言环境中的 GNU,您还可以执行以下操作:查找大小恰好为一个字节的文件,其中(在 shell 中)读取文件的结果为空—— sh 从命令替换中删除尾随换行符。
只是为了提供一种新颖的替代方案,在 FreeBSD 中,可以这样做:
然而,md5 哈希值,即使是小文件,也可能比简单的
cmp
.我尝试找到一种
cmp
使用bash
的命令替换(和 BSDfind
)来表达该方法的方法,但它有点笨拙:同样,多次创建换行文件可能比卡米尔创建一次参考文件并反复比较的方法稍微昂贵一些。