关于bash:如何递归计算目录中的单词数?

How can I count the number of words in a directory recursively?

我正在计算一个项目中的单词数。文件夹有几个级别,其中包含大量文本文件。

有人能帮我找到一个快速的方法吗?

巴什或维姆会很好的!

谢谢


使用find扫描dir树,wc扫描其余

1
$ find path -type f | xargs wc -w | tail -1

最后一行给出总数。


您可以找到并打印所有内容和管道到wc

1
find path -type f -exec cat {} \; -exec echo \; | wc -w

注:如果文件不以换行符结尾,则需要使用-exec echo \;,在这种情况下,一个文件的最后一个字和下一个文件的第一个字不会分开。

或者,您可以找到和wc并使用awk来汇总计数:

1
find . -type f -exec wc -w {} \; | awk '{ sum += $1 } END { print sum }'


TLDR;

1
$ find . -type f -exec wc -w {} + | awk '/total/{print $1}' | paste -sd+ | bc

说明:

find . -type f -exec wc -w {} +将对.所包含的所有文件(递归地)运行wc -w(当前工作目录)。find将尽可能少地执行wc次,但尽可能多地执行ARG_MAX次,以满足系统命令长度限制。当文件数量(和/或其组成长度)超过ARG_MAX时,那么find多次调用wc -w,给出多条total行:

1
2
3
4
5
6
7
8
9
10
11
12
$ find . -type f -exec wc -w {} + | awk '/total/{print $0}'
  8264577 total
  654892 total
 1109527 total
 149522 total
 174922 total
 181897 total
 1229726 total
 2305504 total
 1196390 total
 5509702 total
  9886665 total

通过只打印每个total行的第一个空格分隔字段来隔离这些部分和:

1
2
3
4
5
6
7
8
9
10
11
12
$ find . -type f -exec wc -w {} + | awk '/total/{print $1}'
8264577
654892
1109527
149522
174922
181897
1229726
2305504
1196390
5509702
9886665

paste+分隔符给出中缀和的部分和:

1
2
$ find . -type f -exec wc -w {} + | awk '/total/{print $1}' | paste -sd+
8264577+654892+1109527+149522+174922+181897+1229726+2305504+1196390+5509702+9886665

使用支持中缀表达式和任意精度的bc计算中缀求和:

1
2
$ find . -type f -exec wc -w {} + | awk '/total/{print $1}' | paste -sd+ | bc
30663324

参考文献:

  • https://www.cyberciti.biz/faq/argument-list-too-long-error-solution-解决方案/
  • https://www.in-ulm.de/~mascheck/various/argmax/各种/argmax/
  • https://linux.die.net/man/1/find
  • https://linux.die.net/man/1/wc
  • https://linux.die.net/man/1/awk
  • https://linux.die.net/man/1/paste(粘贴)
  • https://linux.die.net/man/1/bc

如果我从所有bash问题中都学到了一点,那就是一个带有空格的文件名会把你搞得一团糟。即使文件名中有空格,这个脚本也可以工作。

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env bash

shopt -s globstar
count=0
for f in **/*.txt
do
    words=$(wc -w"$f" | awk '{print $1}')
    count=$(($count + $words))
done
echo $count

假设您不需要递归地计数单词,并且您希望包含当前目录中的所有文件,那么您可以使用一种简单的方法,例如:

1
2
3
4
5
6
wc -l *


10  000292_0
500 000297_0
510 total

如果只想计算当前目录中特定扩展名的字数,可以尝试:

1
cat *.txt | wc -l