遇到shell重定向的一个奇怪问题:'消失'的标准输入!

需求:
把找到的文件逐行输出,然后用rm在许可的情况下删除
 
前置准备: 
$ls
rm.sh test1 test2 test3 test4 test5 test6
$cat rm.sh
#! /bin/bash
while read fileinfo
do 
    rm -iv $fileinfo
done< <( find . -name 'test*' -print )

第一次执行结果:

$bash rm.sh

rm:是否删除普通文件“./test2”?

出现的问题:

虽然rm显示了询问信息,却并不关心我输入的是什么(就没给我机会),也没有删除文件

第一次结果分析:
rm -iv需要从标准输入中获取允许,但标准输入已经被重定向为’done< <( find $path -type f -print )‘,所以rm只能从这获取输入了,也造成了这一次执行的令就无效了,然后read和rm就不断地逐次消耗掉输入的行,也就什么都没做了;
 
 第二次前置准备
$ls
rm2.sh test1 test2
$cat test1
test1
test2
test3
test4
test5
test6
 程序解释:
当每次read到的内容不为空就输出到屏幕,count统计的是尝试的删除次数
$cat rm2.sh
#! /bin/bash
count=0
while read info
do
    if [ ! -z info ]
        then echo $info:not null
    fi
    rm -iv test2
    let count++
    echo $count
done< test1

第二次执行结果:

 

$bash rm2.sh
test1:not_null
rm:是否删除普通文件 “test2”?1
test3:not_null
rm:是否删除普通文件 “test2”?2
test5:not_null
rm:是否删除普通文件 “test2”?3
验证分析:
符合第一次结果分析的猜测;
解决方案:
将原标准输入(键盘输入)存放在新的文件描述符中,并在rm中将新的文件描述符作为它的输入
修正后的程序:
$cat rm3.sh
#! /bin/bash
exec 3<&0
while read fileinfo
do 
    rm -iv $fileinfo <&3
done< <( find . -type f -print )
 
 
顺带一提:
'done< <( find . -type f -print )'有两个‘<’的原因:
第一步:‘<( find . -type f -print )’相当于将子shell中的结果输出到一个临时文件
第二步:‘done< temp_file’从临时文件中获取输入
posted @ 2016-01-22 16:39  AnnsShadoW  阅读(1091)  评论(0编辑  收藏  举报