如何让"wc -l"只打印行数而不包含文件名?

220
wc -l file.txt

输出行数和文件名。

我只需要行数本身(不需要文件名)。

我可以做到这一点。

 wc -l file.txt | awk '{print $1}'

也许有更好的方式?


30
wc -l < file.txt 这个命令可以精确而简洁地完成任务。 - Jonathan Leffler
2
可能是重复问题 如何在Bash中获取wc的整数值 - Ciro Santilli OurBigBook.com
6
这是我现在第二次查找的问题。 wc 命令的这种行为对于 Unix 惯用的简洁方式来说是不直观和反范式的。那种简洁性是有原因的,因为你确切地不想绕过所有种类的冗余。毕竟,我知道文件名,不是吗?我想要的是行数。 - Peter - Reinstate Monica
2
@Peter-ReinstateMonica 您可以使用多个参数运行wcwc -l *.txt),这样您将为每个文件获取一行并需要加以区分。 - Kaligule
10个回答

311

尝试这种方法:

wc -l < file.txt

6
在AIX和ksh中,数字前面总是有一个空格。我们需要使用 | awk '{print $1}' 或者 cut 命令来去掉这些空格。另一种去除空格的方法是将其用 echo 命令包裹起来。 - rao
1
@rao是正确的,这会在数字前添加一个空格。我的解决方案解决了这个问题,并且比awk或cut更简单。 - Desi Cochrane
1
@rao,在bash中没有空格。在ksh中,空格从哪里来的?wc -l不应该发出一个空格,为什么ksh会在程序的标准输出前加上一个空格? - Peter - Reinstate Monica
1
虽然这是正确的解决方法(并且足够简单,所以wc从未被修正),但它很可能会更慢且不直观。例如,我希望输出类似于“4711 [stdin]”。 - Peter - Reinstate Monica
1
有人可以解释一下为什么这个代码有效吗? < 这个符号是做什么用的? - mbj
显示剩余2条评论

33
cat file.txt | wc -l

根据man手册(BSD版本,我没有GNU版本可以参考):

如果未指定文件,则使用标准输入,并且不显示文件名。提示符将接受输入,直到接收到EOF或在大多数环境中为[^D]。


5
我不喜欢猫 - 连接操作耗费太多时间。 - pogibas
16
wc -l < file.txt 具有相同的效果。 - pjmorse
2
@user:测试一下。到目前为止,最慢的部分将是从磁盘读取文件。 - sarnold

22

如果不想产生前导空格,为什么不尝试这样做:

wc -l < file.txt | bc

我在这个(Ubuntu 14.04)中遇到了语法错误。我认为文件名有问题。 - MERose
1
在 RHEL 6.7 上会出现错误: $ wc -l file.csv | bc (standard_in) 1: 语法错误 (standard_in) 1: 非法字符:N (standard_in) 1: 语法错误 (standard_in) 1: 语法错误 - Rodrigo Hjort
3
我也遇到了一个解析错误,但你可以结合另一个答案来使用wc -l < file.txt来修复解析错误并去掉空格:wc -l < file.txt | bc - jangosteve

18

技术比较

我曾经遇到一个类似的问题,尝试获取没有wc提供的前导空格的字符计数,这使我来到这个页面。在尝试了这里的答案之后,以下是我在Mac(BSD Bash)上进行个人测试的结果。同样,这是用于字符计数;如果要计算行数,则需要使用wc -lecho -n省略尾随的换行符。

FOO="bar"
echo -n "$FOO" | wc -c                          # "       3"    (x)
echo -n "$FOO" | wc -c | bc                     # "3"           (√)
echo -n "$FOO" | wc -c | tr -d ' '              # "3"           (√)
echo -n "$FOO" | wc -c | awk '{print $1}'       # "3"           (√)
echo -n "$FOO" | wc -c | cut -d ' ' -f1         # "" for -f < 8 (x)
echo -n "$FOO" | wc -c | cut -d ' ' -f8         # "3"           (√)
echo -n "$FOO" | wc -c | perl -pe 's/^\s+//'    # "3"           (√)
echo -n "$FOO" | wc -c | grep -ch '^'           # "1"           (x)
echo $( printf '%s' "$FOO" | wc -c )            # "3"           (√)

总的来说,我不会依靠cut -f* 方法,因为它需要您知道任何给定输出具有的精确前导空格数量。而grep 方法适用于计算行数,但不适用于字符。

bc 是最简洁的,而awkperl 稍微有些过度,但它们都应该相对快速并且足够可移植。

此外,请注意,某些方法可以调整以修剪通用字符串周围的空白(还有echo `echo $FOO`,这是另一个很棒的技巧)。


2
echo $(printf '%s' "$FOO" | wc -c)是一种罕见的情况,其中echo与命令替换不是无用的。 - tripleee
@tripleee 哇...根据你的代码,echo \echo $FOO`;` 也像一个 String.trim() 命令一样作用于变量!太方便了。我也会把你的代码添加到我的回答中。 - Beejor
或许为了上下文,也可以参考何时在shell变量周围加引号 - tripleee

12

怎么样

wc -l file.txt | cut -d' ' -f1
即将 wc 命令的输出导入到 cut 命令中(使用空格作为分隔符,并选择第一个字段)。

5
这并不比 OP 尝试的 wc -l file.txt | awk '{print $1}' 更好。 - doubleDown
1
wc -l < file.txt 方法更快。但在 BSD 上必须使用 | cut -d' ' -f2,只要 wc 命令返回一个前导空格,例如:" 34068289 file.txt",而不是 "34068289 file.txt"。 - Sopalajo de Arrierez
@doubleDown 嗯,使用 awk 就像使用数控机床来切割木板,而不是用锯子。用锯子来锯木头。 - Peter - Reinstate Monica
2
这在 Mac(基于 BSD)上将无法工作。前导空格的数量取决于填充,因此字段值将取决于结果。上面的解决方案中有一个会好得多。 - marco
@SopalajodeArrierez:为什么这种方法比输入重定向更快? - einpoklum
@einpoklum,我不知道为什么,在我的FreeBSD v10上,测试速度更快。也许管道传输比输入重定向更有效率,因为可以避免磁盘使用,至少在处理大文件时是这样的。 - Sopalajo de Arrierez

7

你能行吗?

grep -ch "^" file.txt

5
很好,使用'grep'的创新方式非常独特,但是在我的测试中发现(并不意外)比直接使用更简单/直接的'wc'方法慢2到6倍。 - arielf

4

很明显,此问题有许多解决方案。以下是另一种解决方案:

wc -l somefile | tr -d "[:alpha:][:blank:][:punct:]"

这只会输出行数,但末尾换行符 (\n) 仍存在。如果您不想要它,请将 [:blank:] 更改为 [:space:]


1
当文件名中包含数字时,会出现问题。例如,对于文件test9,其中只有1行内容,输出将为19。 - Raphael Ahrens

4

另一种在不调用外部命令的情况下去除前导零的方法是使用算术扩展$((exp))

echo $(($(wc -l < file.txt)))

1

最好的方法首先是找到目录中的所有文件,然后使用 AWK NR(记录变量数量)

以下是命令:

find <directory path>  -type f | awk  'END{print NR}'

示例:- find /tmp/ -type f | awk 'END{print NR}'


0

这对我来说可行,使用普通的wc -lsed来去除任何不是数字的字符。

wc -l big_file.log | sed -E "s/([a-z\-\_\.]|[[:space:]]*)//g"

# 9249133

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接