3

我想计算*.sav文件$1夹中的文件数。我尝试使用以下命令但它不起作用,这是什么问题?

numOfFiles=`ls $1 | grep -o *\.sav | wc -w`
4

5 回答 5

4

不要解析来自 ls 的输出

请改用 bash 数组。

shopt -s nullglob
sav_files=(*.sav)
echo ${#sav_files[@]}
于 2013-05-31T19:00:52.180 回答
1

主要问题是 *.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 的答案。

于 2013-05-31T18:58:32.160 回答
1

不希望在文件计数中搜索假设问题,但解析输出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 .)

findwith打印所有找到的-print0文件“零结尾”,并且grep -z可以像零分隔的“行”一样读取。-c简单计数找到模式的行(.任何字符)

于 2013-05-31T19:37:46.267 回答
0

您的正则表达式是错误的,*是一个重复运算符,grep但您没有指定要重复的内容。

无论如何,这grep是不必要的;只需将模式指定为 shell glob。

numOfFiles=`ls "$1"/*.sav | wc -l`

注意周围的引号$1和使用行数而不是字数;wc -w将返回 2 的计数underscore_filename

如果您确实使用grep了某些东西,那么将搜索模式放在单引号中通常是个好主意,这样您就不必使用反斜杠转义 shell 元字符。(即使使用反斜杠,您的模式最终也会未转义,因为外壳会在未引用的字符串中吃掉一层转义。)

如果您*.sav在当前目录中有任何匹配项,则未引用的正则表达式将被 shell 扩展为一个 glob,并产生可能很难调试的有趣结果。

于 2013-05-31T18:59:24.080 回答
0

我个人建议在变量周围使用引号来防止空格成为问题。

此外,wc -l这是一个更好的解决方案,因为它计算行而不是单词(带有空格的文件可能会计算两次)。

所以试试这个:

numOfFiles=$(ls -1 "$1/"*.sav | wc -l)
于 2013-05-31T19:00:00.993 回答