30

特定のディレクトリ内のすべての*binファイルを計算したい。当初、私はfor-loop:で作業していました

var=0
for i in *ls *bin
do
   perform computations on $i ....
   var+=1
done
echo $var

ただし、一部のディレクトリではファイルが多すぎてエラーが発生します。Argument list too long

したがって、私はパイプでそれを試していましたwhile-loop

var=0
ls *.bin | while read i;
do
  perform computations on $i
  var+=1
done
echo $var

ここでの問題は、作成されたパイプサブシェルを使用することです。したがって、を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
4

4 に答える 4

78

問題は、while ループがサブシェルで実行されることです。while ループが終了した後、サブシェルのコピーvarは破棄され、var親のオリジナル (値は変更されていません) がエコーされます。

これを修正する 1 つの方法は、以下に示すようにプロセス置換を使用することです。

var=0
while read i;
do
  # perform computations on $i
  ((var++))
done < <(find . -type f -name "*.bin" -maxdepth 1)

他の回避策については、BashFAQ/024を参照してください。

を解析するのは良い習慣ではないため、 にも置き換えlsたことに注意してください。findls

于 2012-12-05T15:51:21.880 に答える
16

POSIX 準拠のソリューションは、パイプ (p ファイル) を使用することです。このソリューションは非常に優れており、移植性があり、POSIX ですが、ハードディスクに何かを書き込みます。

mkfifo mypipe
find . -type f -name "*.bin" -maxdepth 1 > mypipe &
while read line
do
    # action
done < mypipe
rm mypipe

パイプはハードディスク上のファイルです。不要なファイルが残るのを避けたい場合は、忘れずに削除してください。

于 2016-09-18T15:45:29.837 に答える
-2

これは、for ループでも実行できます。

var=0;
for file in `find . -type f -name "*.bin" -maxdepth 1`; do 
    # perform computations on "$i"
    ((var++))
done 
echo $var
于 2016-05-12T09:21:04.343 に答える