在这里遇到麻烦。我想将ls命令的输出捕获到变量中。然后使用该变量并计算其中的行数。我尝试了一些变化
这样可行,但如果没有.txt文件,则表示计数为1:
testVar=`ls -1 *.txt`
count=`wc -l <<< $testVar`
echo '$count'
这适用于没有.txt文件的情况,但是当有.txt文件时,计数会短1:
testVar=`ls -1 *.txt`
count=`printf '$testVar' | wc -l`
echo '$count'
此变体还表示存在NO .txt文件时计数为1:
testVar=`ls -1 *.txt`
count=`echo '$testVar' | wc -l`
echo '$count'
编辑:我应该提到这是korn shell。
答案 0 :(得分:2)
正确的方法是使用数组。
# Use ~(N) so that if the match fails, the array is empty instead
# of containing the pattern itself as the single entry.
testVar=( ~(N)*.txt )
count=${#testVar[@]}
答案 1 :(得分:2)
这个小问题实际上包括三个标准shell陷阱(bash和korn shell)的结果:
如果这些字符串(<<<...
)不以新行结尾,则会向其添加换行符。这使得无法使用here-string向命令发送完全空的输入。
从命令替换(cmd
或最好$(cmd)
)中使用的命令的输出中删除所有尾随换行符。所以你无法知道输出结尾有多少空行。
(不是真的是一个shell getcha,但它出现了很多)。 wc -l
计算换行符的数量,而不是行数。所以最后一行&#34;&#34;如果没有以换行符终止,则不计算在内。 (不以换行符结尾的非空文件不是符合Posix的文本文件。所以这样奇怪的结果并不出乎意料。)
所以,当你这样做时:
var=$(cmd)
utility <<<"$var"
第一行中的命令替换删除所有尾随换行符,然后第二行中的here-string扩展将恰好放回一个尾随换行符。这会将空输出转换为单个空行,否则会从输出的末尾删除空白行。
所以utility
是wc -l
,那么除非输出为空,否则你将获得正确的计数,在这种情况下,它将是1而不是0。
另一方面,用
var=$(cmd)
printf %s "$cmd" | utility
如前所述,通过命令替换删除尾随换行符,因此printf
使最后一行(如果有)未终止。现在,如果utility
为wc -l
,如果输出为空,则最终为0,但对于非空文件,计数将不包括输出的最后一行。
一种可能的与shell无关的解决方法是使用第二个选项,但使用grep ''
作为过滤器:
var=$(cmd)
printf %s "${var}" | grep '' | utility
空图案&#39;&#39;将匹配每一行,grep
总是终止每一行输出。 (当然,这仍然不会在输出结束时计算空白行。)
说了这么多,尝试解析ls
的输出总是一个坏主意,甚至只是计算文件数。 (例如,文件名可能包含换行符。)因此,最好使用glob扩展结合一些特定于shell的方法来计算glob扩展中的对象数(以及其他一些特定于shell的检测方法)当没有文件与glob匹配时。)
答案 2 :(得分:0)
你也可以这样使用:
#!/bin/bash
testVar=`ls -1 *.txt`
if [ -z "$testVar" ]; then
# Empty
count=0
else
# Not Empty
count=`wc -l <<< "$testVar"`
fi
echo "Count : $count"
答案 3 :(得分:0)
我打算建议这个,这是我在bash中使用的一个结构:
f=($(</path/to/file))
echo ${#f[@]}
要处理多个文件,您只需添加文件。
f=($(</path/to/file))
f=+($(</path/to/otherfile))
或
f=($(</path/to/file) $(</path/to/otherfile))
要处理大量文件,您可以循环:
f=()
for file in *.txt; do
f+=($(<$file))
done
然后我看到了chepner的反应,我收集的反应比我的反应更为明显。
注意:循环优于parsing ls。