循环输出管道防止局部变量修改

tjm*_*tjm 11 shell scripting bash pipe shell-script

我正在尝试编写一个简单的 bash 函数,该函数将许多文件和/或目录作为其参数。这应该:

  1. 完全限定文件名。
  2. 对它们进行排序。
  3. 删除重复项。
  4. 打印所有实际存在的内容。
  5. 返回不存在的文件数。

我有一个脚本,几乎可以满足我的要求,但是排序失败了。脚本的返回值是正确的,但输出不是(未排序和重复)。如果我| sort -u按照指示取消注释该语句,则输出是正确的,但返回值始终为0.

NB 解决问题的更简单的解决方案是受欢迎的,但问题实际上是关于为什么我的代码中会发生这种情况。也就是说,为什么添加管道似乎会阻止脚本增加变量r

这是脚本:

function uniqfile
{
    local r=0 

    for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done #| sort -u    ## remove that comment

    return $r
}
Run Code Online (Sandbox Code Playgroud)

enz*_*tib 16

由于此功能,这是众所周知的 bash 陷阱:

管道中的每个命令都作为单独的进程(即,在子外壳中)执行。

这样修改后的变量对于子shell是本地的,并且一旦回到父级就看不到了。

为避免这种情况,请改写您的代码以避免管道,并使用进程替换:

 for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done > >(sort -u)
Run Code Online (Sandbox Code Playgroud)

  • @tjm:它被称为*进程替换* (2认同)