tee 在 Bash 脚本中以不正确的顺序显示输出

tee 在 Bash 脚本中以不正确的顺序显示输出

我正在为大学作业编写一个 bash 脚本,其中需要对某个目录执行多个操作(作为脚本的参数)。

  1. 显示具有特定权限的所有文件/目录(权限以八进制格式的参数给出)
  2. 显示目录树中最近 x 天内修改的文件(x 是一个参数)
  3. 显示最近 x 天内访问过的树的子目录(x 与上面使用的参数相同)
  4. 显示目录中所有管道/插座类型文件
  5. 显示目录中的所有空文件(不在任何子目录中)

在每次操作结束时,脚本还应显示找到的文件(或子目录)的数量。

我正在使用此命令来打印所需的输出(例如操作1):echo "$files_perms" | tee >(echo "Files found: $(wc -l)")

问题是,tee在第一个和第二个之后的操作中,输出没有以正确的顺序显示。

第一次操作(输出正常):

第二次操作(输出仍然正常):

第三、第四和第五个操作(输出顺序混乱 - 箭头表示tee每个操作的输出,op3-op5 是每个操作的实际输出):

以下是每个函数的代码:

#display files in the current directory tree with the specified permissions
sub1 () {
    files_perms=$(ls $1 -l | grep $2 --color=never)
    echo "$files_perms" | tee >(echo "Files found: $(wc -l)")
    echo ""
}

#display files in the current directory tree that were modified within the last $2 days (without hidden files)
sub2 () {
    files_modlastxdays=$(find $1 -not -path '*/.*' -type f -mtime -$2)
    echo "$files_modlastxdays" | tee >(echo "Files found: $(wc -l)")
    echo ""
}

#display subdirectories in the current directory tree that were accessed within the last $2 days (without hidden subdirs)
sub3 () {
    subdirs_acclastxdays=$(find $1 -not -path '*/.*' -type d -atime -$2)
    echo "$subdirs_acclastxdays" | tee >(echo "Subdirectories found: $(wc -l)")
    echo ""
}

#display all files that are of pipe/socket type in the current directory tree
sub4 () {
    ps_files=$(find $1 \( -type p -o -type s \))
    echo "$ps_files" | tee >(echo "Files found: $(wc -l)")
    echo ""
}

#display all empty files in current directory (NOT in subdirectories)
sub5 () {
    empty_files=$(find $1 -maxdepth 1 -type f -empty)
    echo "$empty_files" | tee >(echo "Files found: $(wc -l)")
    echo ""
}

函数调用如下:

echo "Files with permission $1 ($rwx_converted):"
sub1 $3 $rwx_converted

echo "Files that were modified within the last $2 days:"
sub2 $3 $2

echo "Subdirectories that were accessed within the last $2 days:"
sub3 $3 $2

echo "Files that are of pipe/socket type:"
sub4 $3

echo "Empty files (NOT in subdirectories):"
sub5 $3

$1是八进制格式的文件权限参数(rwx_converted是将八进制格式转换为rwx格式),

$2是操作 2 和 3 的 x 天参数,

是用于/命令$3的目录参数。lsfind

脚本执行示例:bash labscript2.sh 755 8 /home/na-no

为什么的输出没有以正确的顺序显示(在每个/命令tee的末尾和lsfind不是在一堆行之后)?

答案1

您有多个并发进程同时运行。输出顺序将取决于哪个进程首先写入。

例如,您的第四个似乎tee已开始写入输出,而第三个wc仍在处理其输入。

考虑:

#!/bin/bash

echo 1 | tee >(sleep 8; echo 1b) >(sleep 4; echo 1c)
echo 2 | tee >(sleep 2; echo 2b) >(sleep 6; echo 2c)
echo 3 | tee >(         echo 3b) >(         echo 3c)

echo done

请注意,tee一旦完成将输入复制到所有输出,就会退出。然而,由 bash 的进程替换启动的进程是异步运行的,并且在(甚至脚本本身)退出>(...)后可能仍在运行。tee

另请注意,未定义tee首先写入哪个输出。如果所有输出实际上都是同一个文件,则输出更有可能混合在一起。例如,在我的机器上,tee上面的第三行输出:

3b
3c
3

ie 似乎是在其他输出之后stdout写入tee的,这意味着不能保证您会wc按照您期望的顺序获得输出。

相关内容