Bash脚本:While-Loop子壳困境
我想计算一个给定目录内的所有* bin文件。 最初我正在使用一个for-loop
:
var=0 for i in *ls *bin do perform computations on $i .... var+=1 done echo $var
但是,在某些目录中有太多的文件导致错误: Argument list too long
因此,我正在用一个pipe道while-loop
尝试它:
var=0 ls *.bin | while read i; do perform computations on $i var+=1 done echo $var
现在的问题是通过使用pipe子的子壳来创build。 因此, echo $var
返回0
。
我该如何处理这个问题呢?
原来的代码:
#!/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 "\tEntropy: $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 "===================================================\n" | tee -a entropy.txt echo -e "Accumulated Entropy:\t$acc_entropy ($count files processed)\n" | tee -a entropy.txt
问题是while循环在子shell中执行。 在while循环终止之后, var
的副本的副本被丢弃,并且回显父值(其值不变)的原始var
。
解决这个问题的一个方法是使用Process Substitution ,如下所示:
var=0 while read i; do # perform computations on $i ((var++)) done < <(find . -type f -name "*.bin" -maxdepth 1)
看看BashFAQ / 024的其他解决方法。
注意我也用ls
replace了ls
,因为parsingls
不是好习惯。
符合POSIX标准的解决scheme是使用pipe道(p文件)。 这个解决scheme非常好,便携和POSIX,但是在硬盘上写了一些东西。
mkfifo mypipe find . -type f -name "*.bin" -maxdepth 1 > mypipe & while read line do # action done < mypipe rm mypipe
您的pipe道是您的硬盘上的文件。 如果你想避免有无用的文件,不要忘记删除它。
这也可以用for循环来完成:
var=0; for file in `find . -type f -name "*.bin" -maxdepth 1`; do # perform computations on "$i" ((var++)) done echo $var