zoukankan      html  css  js  c++  java
  • 遇到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’从临时文件中获取输入
  • 相关阅读:
    docker使用
    解决wps linux中文字体名字全是英文
    解决小程序云函数操作数据库回调不执行
    解决XP“不是有效Win32程序” 不是改Platform toolset
    [hdu1686] Oulipo【KMP】
    [poj 2104] K-th Number【主席树】
    bzoj2806 [Apio2012]dispatching【可并堆】
    bzoj1492 [NOI2007]货币兑换Cash【cdq分治】
    [coci2015-2016 coii] torrent【树形dp 二分】
    [coci2015-2016 coii] Palinilap【字符串 哈希】
  • 原文地址:https://www.cnblogs.com/annsshadow/p/5151707.html
Copyright © 2011-2022 走看看