遇到shell重新導向的一個奇怪問題:'消失'的標準輸入!,shell重新導向
需求:把找到的檔案逐行輸出,然後用rm在許可的情況下刪除 前置準備:
$lsrm.sh test1 test2 test3 test4 test5 test6
$cat rm.sh#! /bin/bashwhile read fileinfodo rm -iv $fileinfodone< <( find . -name 'test*' -print )
第一次執行結果:
$bash rm.shrm:是否刪除普通檔案“./test2”?
出現的問題:
雖然rm顯示了詢問資訊,卻並不關心我輸入的是什麼(就沒給我機會),也沒有刪除檔案
第一次結果分析:rm -iv需要從標準輸入中擷取允許,但標準輸入已經被重新導向為’done< <( find $path -type f -print )‘,所以rm只能從這擷取輸入了,也造成了這一次執行的令就無效了,然後read和rm就不斷地逐次消耗掉輸入的行,也就什麼都沒做了;
第二次前置準備:
$lsrm2.sh test1 test2
$cat test1test1test2test3test4test5test6
程式解釋:當每次read到的內容不為空白就輸出到螢幕,count統計的是嘗試的刪除次數
$cat rm2.sh#! /bin/bashcount=0while read infodo if [ ! -z info ] then echo $info:not null fi rm -iv test2 let count++ echo $countdone< test1
第二次執行結果:
$bash rm2.shtest1:not_nullrm:是否刪除普通檔案 “test2”?1test3:not_nullrm:是否刪除普通檔案 “test2”?2test5:not_nullrm:是否刪除普通檔案 “test2”?3
驗證分析:符合第一次結果分析的猜測;
解決方案:將原標準輸入(鍵盤輸入)存放在新的檔案描述符中,並在rm中將新的檔案描述符作為它的輸入
修正後的程式:
$cat rm3.sh#! /bin/bashexec 3<&0while read fileinfodo rm -iv $fileinfo <&3done< <( find . -type f -print )
順帶一提:'done< <( find . -type f -print )'有兩個‘<’的原因:第一步:‘<( find . -type f -print )’相當於將子shell中的結果輸出到一個臨時檔案第二步:‘done< temp_file’從臨時檔案中擷取輸入