我想计算*.sav
文件$1
夹中的文件数。我尝试使用以下命令但它不起作用,这是什么问题?
numOfFiles=`ls $1 | grep -o *\.sav | wc -w`
主要问题是 *.sav 不是正则表达式,它是一个 glob。您可能想要 grep for ,由于过时的语法\.sav
,您必须为 shell 转义一次,然后再转义一次:``
numOfFiles=`ls $1 | grep -o \\\\.sav | wc -w`
此外,您不应该解析 , 的输出ls
,并且wc -w
会导致带有空格的文件名被计算多次。
更好的解决方案是使用 find:
numOfFiles=$(find "$1" -maxdepth 1 -name '*.sav' | wc -l)
要获得更好的 Bash 特定解决方案,请参阅 1_CR 的答案。
不希望在文件计数中搜索假设问题,但解析输出ls
有时可能是错误的想法。自己试试,创建一个文件:
touch 'aa bb
cc.sav'
space
因此,使用和newline
以其名称创建文件。通常任何ls
解析都会失败。
1_CR 的解决方案是 NICE 和 ELEGANT。
如果您出于某种原因不喜欢它,您可以使用find
并且不要使用wc
,因为wc
例如失败是最后一行不包含换行符。(wc 不计算行数,而是\n
字符数。
接下来会给出正确答案:
numOfFiles=$(find . -maxdepth 1 -name \*.sav -print0 | grep -zc .)
find
with打印所有找到的-print0
文件“零结尾”,并且grep -z
可以像零分隔的“行”一样读取。-c
简单计数找到模式的行(.
任何字符)
您的正则表达式是错误的,*
是一个重复运算符,grep
但您没有指定要重复的内容。
无论如何,这grep
是不必要的;只需将模式指定为 shell glob。
numOfFiles=`ls "$1"/*.sav | wc -l`
注意周围的引号$1
和使用行数而不是字数;wc -w
将返回 2 的计数underscore_filename
。
如果您确实使用grep
了某些东西,那么将搜索模式放在单引号中通常是个好主意,这样您就不必使用反斜杠转义 shell 元字符。(即使使用反斜杠,您的模式最终也会未转义,因为外壳会在未引用的字符串中吃掉一层转义。)
如果您*.sav
在当前目录中有任何匹配项,则未引用的正则表达式将被 shell 扩展为一个 glob,并产生可能很难调试的有趣结果。
我个人建议在变量周围使用引号来防止空格成为问题。
此外,wc -l
这是一个更好的解决方案,因为它计算行而不是单词(带有空格的文件可能会计算两次)。
所以试试这个:
numOfFiles=$(ls -1 "$1/"*.sav | wc -l)