问题描述
我想计算给定目录中的所有 *bin 文件.最初我使用 for-loop
:
i want to compute all *bin files inside a given directory. Initially I was working with a for-loop
:
var=0
for i in *ls *bin
do
perform computations on $i ....
var+=1
done
echo $var
但是有些目录文件太多导致报错:Argument list too long
However, in some directories there are too many files resulting in an error: Argument list too long
因此,我尝试使用管道while-loop
:
Therefore, I was trying it with a piped while-loop
:
var=0
ls *.bin | while read i;
do
perform computations on $i
var+=1
done
echo $var
现在的问题是通过使用管道创建子壳.因此,echo $var
返回 0
.
我该如何处理这个问题?
原始代码:
The problem now is by using the pipe subshells are created. Thus, echo $var
returns 0
.
How can I deal with this problem?
The original Code:
#!/bin/bash
function entropyImpl {
if [[ -n "$1" ]]
then
if [[ -e "$1" ]]
then
echo "scale = 4; $(gzip -c ${1} | wc -c) / $(cat ${1} | wc -c)" | bc
else
echo "file ($1) not found"
fi
else
datafile="$(mktemp entropy.XXXXX)"
cat - > "$datafile"
entropy "$datafile"
rm "$datafile"
fi
return 1
}
declare acc_entropy=0
declare count=0
ls *.bin | while read i ;
do
echo "Computing $i" | tee -a entropy.txt
curr_entropy=`entropyImpl $i`
curr_entropy=`echo $curr_entropy | bc`
echo -e " Entropy: $curr_entropy" | tee -a entropy.txt
acc_entropy=`echo $acc_entropy + $curr_entropy | bc`
let count+=1
done
echo "Out of function: $count | $acc_entropy"
acc_entropy=`echo "scale=4; $acc_entropy / $count" | bc`
echo -e "===================================================
" | tee -a entropy.txt
echo -e "Accumulated Entropy: $acc_entropy ($count files processed)
" | tee -a entropy.txt
推荐答案
问题在于 while 循环是在子 shell 中执行的.while 循环结束后,子shell 的var
副本被丢弃,并回显父级的原始var
(其值不变).
The problem is that the while loop is executed in a subshell. After the while loop terminates, the subshell's copy of var
is discarded, and the original var
of the parent (whose value is unchanged) is echoed.
解决此问题的一种方法是使用 Process Substitution,如图所示下面:
One way to fix this is by using Process Substitution as shown below:
var=0
while read i;
do
# perform computations on $i
((var++))
done < <(find . -type f -name "*.bin" -maxdepth 1)
查看 BashFAQ/024 以了解其他解决方法.
Take a look at BashFAQ/024 for other workarounds.
请注意,我还用 find
替换了 ls
,因为 解析ls
.
Notice that I have also replaced ls
with find
because it is not good practice to parse ls
.
这篇关于Bash 中的 While 循环子外壳困境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!