Bash 中的 While 循环子外壳困境 [英] While-loop subshell dilemma in Bash

查看:26
本文介绍了Bash 中的 While 循环子外壳困境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想计算给定目录中的所有 *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 循环子外壳困境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆