我正在尝试编写一个shell脚本,它将计算格式为.c
和.h
的目录(及其子目录)中每个文件中所有行的总和。
我已经拥有该代码,但我不确定如何找到这两种文件格式。
!/bin/bash
#Program
total=0
find /path -type f -name "*.php" | while read FILE; do
count=$(grep -c ^ < "$FILE")
echo "$FILE has $count lines"
let total=total+count
done
echo TOTAL LINES COUNTED: $total
我是shell / bash的新手,如果有任何其他错误,我将不胜感激。
答案 0 :(得分:4)
优化和快 find
+ GNU parallel
解决方案:
find /path -type f -name "*.[ch]" -print0 | parallel -q0 -j0 --no-notice wc -l {} \
| awk '{ sum+=$1 }END{ print "TOTAL LINES COUNTED: "sum }'
-print0
- 在标准输出上打印完整文件名,后跟空字符(而不是-print
使用的换行符)。这允许处理 find
输出的程序正确解释包含换行符或其他类型的空格的文件名。 parallel
命令wc -l {}
将针对每个文件并行(这称为并行处理)答案 1 :(得分:2)
要查找.c
和.h
个文件而不是.php
,
只需将-name
参数的值更改为*.[ch]
。
脚本中还有一些其他问题:
IFS= read -r
#!/bin/bash
,而不是!/bin/bash
可能会有一些小的改进:
((...))
语法(算术上下文)把它放在一起:
#!/bin/bash
total=0
find /path -type f -name "*.[ch]" | while IFS= read -r file; do
count=$(grep -c ^ < "$file")
echo "$file has $count lines"
((total += count))
done
echo TOTAL LINES COUNTED: $total
其他答案推荐find ... -exec wc -l
的变体。
虽然看起来更优雅,
它们的工作方式与脚本完全不同:
wc -l
计算的行数与grep -c ^
略有不同。特别是它不计算文件的最后一行,如果它不以换行符结束。试试例如printf hello > file; wc -l file; grep -c ^ file
- &gt;你会得到0和1。find ... -exec wc -l {} +
非常接近(如果find
的实施支持+
),但同样会出现需要特殊处理的极端情况。例如,如果文件太多,则会多次调用wc
,从而生成需要协调的多个子总计。答案 2 :(得分:1)
试试这个:
cat $(find /path -type f \( -name '*.c' -o -name '*.h' \)) |wc -l
它会在cat
返回的每个文件上运行find
,并将输出传递到wc
。如果您需要变量中的值,请执行此操作
lines=$(cat ...)
echo counted $lines lines
答案 3 :(得分:1)
将所有文件以.c
或.h
结尾并输入grep -c
:
find -type f -name '*.[ch]' -exec cat {} + | grep -c '^'
对于没有+
选项的查找,替代方法是
find -type f -name '*.[ch]' -exec cat {} \; | grep -c '^'
每个文件调用一次cat
而不是尽可能少的几次,使其慢一点。
如果您知道不会有很多文件接近命令行长度限制,那么您可以使用shell globbing:
shopt -s globstar # enable **/* glob
cat **/*.[ch] | grep -c '^'