快速删除少于 x 行的文件的方法

快速删除少于 x 行的文件的方法

在 bash 中,有什么快速且不太复杂的方法可以删除目录中 x 行以下的所有文件?

答案1

这是一个 POSIX 解决方案,应该非常容易理解:

find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;

如在斯蒂芬的回答,删除echo当满意的时候就会删除。


为 Unix/Linux 新手编写的解释:

.代表当前目录。 find在 中递归查找文件和目录.,并可以对它们执行操作。

-type是其中find之一初选;这是一个将对递归找到的每个文件和目录(在 内)执行的测试.,并且仅在结果为“true”时才评估该行上的其余主项。

在这种特殊情况下,只有当我们正在处理一个常规文件,而不是目录或其他东西(例如块设备。)


-exec节点 ( 的find) 调用外部命令,并且只有在外部命令成功退出(退出状态为“0”)时才继续执行下一个主节点。{}被命令“考虑”的文件名替换find。所以第一次-exec调用相当于下面的shell命令,依次对每个文件执行:

awk -v x=10 'NR==x{exit 1}' ./somefilename

awk 本身就是一门完整的语言,设计用于处理分隔文本文件,例如 CSV。 Awk 条件和命令(包含在单引号之间并以字母 开头NR)针对文本文件的每一行执行。 (隐式循环。)

要充分学习 Awk,我强烈推荐格莱莫尔教程,但我将解释上述命令中使用的 Awk 功能。


Awk标志-v允许我们在执行 Awk 命令之前(针对文件的每一行)设置一个 Awk 变量(一次)。在本例中,我们设置x10


NR是一个特殊的 Awk 变量,指的是“当前的数量ecord。”换句话说,它是我们在循环中的任何特定传递中查看的行号。

(请注意,它尽管不寻常,但可能使用不同的“埃科德Separator" 比默认的换行符,通过设置RS. 这是使用记录分隔符播放的示例。


awk 脚本一般包括状况(花括号外)结合行动(在大括号内。)可以有复合条件和复合操作,并且有一个默认条件(true)和一个默认操作(print),但我们不需要理会这些。

状况这是“这是第 10 行吗?”如果是这种情况,我们将以非零退出状态退出,这在 shell 脚本中意味着“命令终止失败”。

因此该 Awk 命令退出的唯一方法成功地是指在到达第 10 行之前是否到达文件末尾。

因此,如果 awk 脚本成功退出,则意味着您有一个少于十行的文件。


下一个-exec调用(如果删除echo)将通过运行以下命令删除每个文件(在评估 的初选中达到如此程度find):

rm -f ./somefilename

答案2

假设一个find支持-readable谓词的实现(如果您find不支持它,只需将其删除,您只会收到不可读文件的错误消息,或替换为-exec test -r {} \;):

x=10 find . -type f -readable -exec sh -c '
  for file do
    lines=$(wc -l < "$file") && [ "$((lines))" -lt "$x" ] && echo rm -f "$file"
  done' sh {} +

删除echo如果高兴。

这并不是特别有效,因为它很重要全部每个文件中的行,而它只需要停在第x一个文件,并且它为每个文件运行一个wc(也可能是一个rm)命令。

使用 GNU awk,您可以通过以下方式提高效率:

x=10
find . -type f -readable -exec awk -v x="$x" -v ORS='\0' '
  FNR == x {nextfile}
  ENDFILE {if (FNR < x) print FILENAME}' {} +|
  xargs -r0 echo rm -f

(再次,echo高兴时删除)。

与以下相同perl

x=10 find . -type f -readable -exec perl -Tlne '
  if ($. == $ENV{x}) {close ARGV}
  elsif (eof) {print $ARGV; close ARGV}' {} +

print如果高兴的话就换成unlink

答案3

为了完整起见,除了 AWK 之外,您还可以使用 GNU sed 来实现相同的结果:

find . -type f -exec sed 11q1 '{}' ';' -exec echo rm -f '{}' ';'

这会导致命令行更加简洁。

解释

11 - is the address, i.e. "the eleventh line"
q - is for _q_uit (abort the execution)
1 - is the exit code parameter for q (GNU sed extension) 

相关内容