你的位置:首页 > 操作系统

[操作系统]遇到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’从临时文件中获取输入