如何递归地找到目录树中每个文件第一行的第一个字符是空格、制表符或换行符的所有文件?

如何递归地找到目录树中每个文件第一行的第一个字符是空格、制表符或换行符的所有文件?

例如:

我有两个文件,a.txt 和 b.txt:

a.txt

line 1
line 2

b.txt

 line 1
line 2

在这种情况下,b.txt 应该出现在列表中,因为第一行的第一个字符是空格、制表符或换行符。

答案1

尝试这个 :

find . -type f -exec awk 'NR==1 && /^\s/{print FILENAME}' {} \;

或者使用4:

shopt -s globstar
awk 'NR==1 && /^\s/{print FILENAME} **/*

答案2

zsh

starts_with_space() {
  local c
  read -ku0 c < ${1-$REPLY} && [[ $c = [$' \t\n'] ]]
}
printf '%s\n' **/*(D.L+0+starts_with_space)
  • D包含点文件(隐藏文件)并像这样进入隐藏目录find
  • .仅常规文件(如find's -type f
  • L+0:仅非空文件(如find's -size +0c
  • +starts_with_space仅那些starts_with_space返回 true 的。

这样做的好处之一find是它为您提供了一个排序的文件名列表。它仅从每个文件中读取一个字符(在具有多字节字符集的语言环境中可能不止一个字节)。

答案3

正确的方法是与find+awk命令:

find . -type f -size +0c -exec awk '{ exit (/^[[:space:]]/? 0 : 1) }' {} \; -print

exit语句导致awk立即停止执行当前规则并停止处理输入;任何剩余的输入都将被忽略。退出语句的写法如下:

exit [return code]

如果提供退出参数,则其值将用作进程的退出状态awk代码

find-printawk仅当进程提供退出状态时才会执行操作0


更简化的方法如下:

find . -type f -size +0c -exec awk '{ exit (!NF? 0 : 1) }' {} \; -print

答案4

解决方案与awk最后。

使用 GNU sed(支持sed以显式退出状态退出脚本):

find . -type f -size +0c -exec sed -n '1{/^[^[:blank:]]/q 1};q' {} ';' -print

-size +0c可确保不报告完全为空的文件。

如果当前目录包含问题中的两个文件和c.txt一个第一行为空的额外文件,则会生成

./b.txt
./c.txt

GNUsed脚本:

1{
    /^[^[:blank:]]/q 1
}
q

对于第 1 行,它检查该行的第一个字符是否为非空白(不是空格或制表符),如果是,则以退出状态 1 ( q 1) 退出。否则,它将以退出状态零(最后一个q)退出。

空的第一行将不匹配/^[^[:blank:]]/,因此可以正确处理这种情况。

如果sed以零退出状态退出,-print将导致文件的路径名被打印到标准输出find


等效的东西,但是使用awk(任何都awk可以):

find . -type f -size +0c -exec awk '/^[^[:blank:]]/ { e=1 } { exit e }' {} ';' -print

相关内容