在Bash Shell中,管道的最後一個命令都是在子Shell中執行的。這意味着在子Shell中賦值的變量對父Shell是無效的。所以當我們將管道輸出傳送到一個循環結構,填入隨後將要使用的變量,那麼就會產生很多問題。一旦循環完成,其所依賴的變量就不存在了。
[root@xieqichao ~]
ls -l | grep -v total | while read line
do
all="$all $line"
echo $line
done
echo "all = " $all
CTRL+D
[root@xieqichao ~]
-rw-r--r--. 1 root root 193 Nov 24 11:25 outfile
-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh
-rwxr-xr-x. 1 root root 108 Nov 24 12:48 test8_1.sh
all =
爲了解決該問題,我們可以將while之前的命令結果先輸出到一個臨時文件,之後再將該臨時文件作爲while的重定向輸入,這樣while內部和外部的命令都將在同一個Shell內完成。
[root@xieqichao ~]
ls -l | grep -v total > outfile
while read line
do
all="$all $line"
echo $line
done < outfile
rm -f outfile
echo "all = " $all
CTRL+D
[root@xieqichao ~]
-rw-r--r--. 1 root root 0 Nov 24 12:58 outfile
-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh
-rwxr-xr-x. 1 root root 140 Nov 24 12:58 test8_2.sh
all = -rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh -rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_2.sh
上面的方法只是解決了該問題,然而卻帶來了一些新問題,比如臨時文件的產生容易導致性能問題,以及在腳本異常退出時未能及時刪除當前使用的臨時文件,從而導致生成過多的垃圾文件等。下面將再介紹一種方法,該方法將同時解決以上兩種方法同時存在的問題。該方法是通過HERE-Document的方式來替代之前的臨時文件方法。
[root@xieqichao ~]
OUTFILE=`ls -l | grep -v total`
while read line
do
all="$all $line"
echo $line
done <<EOF
$OUTFILE
EOF
echo "all = " $all
CTRL+D
[root@xieqichao ~]
-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh
-rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_3.sh
all = -rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh -rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_3.sh