我想计算*.sav
文件夹中$1
个文件的数量。
我尝试使用以下命令,但它不起作用,有什么问题?
numOfFiles=`ls $1 | grep -o *\.sav | wc -w`
答案 0 :(得分:4)
Do not parse the output from ls
改为使用bash数组。
shopt -s nullglob
sav_files=(*.sav)
echo ${#sav_files[@]}
答案 1 :(得分:1)
主要问题是* .sav不是正则表达式,它是一个glob。你可能想要\.sav
grep,你必须为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的答案。
答案 2 :(得分: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 .)
find
-print0
打印所有找到的文件“零结束”,grep -z
可以读取零划分的“行”。 -c
简单计数找到模式.
(任何字符)
答案 3 :(得分:0)
您的正则表达式错误,*
是grep
的重复运算符,但您没有指定要重复的内容。
无论如何,grep
是不必要的;只需将模式指定为shell glob。
numOfFiles=`ls "$1"/*.sav | wc -l`
请注意$1
周围的引号以及使用行数而不是字数;对于wc -w
,underscore_filename
将返回两个计数。
如果你确实使用grep
,那么将搜索模式放在单引号中通常是个好主意,因此你不必使用反斜杠转义shell元字符。 (即使使用反斜杠,你的模式最终也会被转义,因为shell会在未加引号的字符串中占用一级转义。)
如果当前目录中的*.sav
上有任何匹配项,那么未引用的正则表达式将由shell扩展为glob,并产生有趣的结果,这可能很难调试。
答案 4 :(得分:0)
就个人而言,我建议在变量周围使用引号以防止出现空格问题。
此外,wc -l
是一个更好的解决方案,因为它计算行而不是单词(带空格的文件可能会计数两次)。
所以试试这个:
numOfFiles=$(ls -1 "$1/"*.sav | wc -l)