在Bash中拆分和循环实时命令输出

时间:2016-10-11 04:45:45

标签: bash shell

我正在归档并使用split生成多个部分,同时还打印输出文件(来自STDERR上的split,我将其重定向到STDOUT)。但是,输出数据的循环直到命令返回后才会发生。

无论如何在命令返回之前主动拆分STDOUT输出?

以下是我目前拥有的内容,但它只在命令返回后打印文件名列表:

export IFS=$'\n'
for line in `data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>&1`; do
    FILENAME=`echo $line | awk '{ print $3 }'`
    echo "    - $FILENAME"
done

3 个答案:

答案 0 :(得分:1)

试试这个:

data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>&1 | while read -r line
do
    FILENAME=`echo $line | awk '{ print $3 }'`
    echo "    - $FILENAME"
done

但是请注意,while循环中设置的任何变量都不会在循环后保留它们的值(while循环在子shell中运行。)

答案 1 :(得分:1)

没有理由进行for循环或读取或回声。只需将流传输到awk:

... | split -d -b $CHUNK_SIZE --verbose - test 2>&1 |
 awk '{printf "    - %s\n", $3 }'

你会看到缓冲的延迟,但除非你的系统很慢或者你非常敏锐,否则你不太可能注意到它。

答案 2 :(得分:0)

命令替换需要 1 才能在for循环开始之前运行。

for item in $(command which produces items); do ...

while read -r一旦产生第一行就会开始消耗输出(或者更实际地,只要输出缓冲区已满):

command which produces items |
while read -r item; do ...

1 嗯,从设计的角度来看,它绝对不是需要,我想,但这就是它目前的工作方式。

正如William Pursell已经指出的那样,没有特别的理由在while read循环中运行Awk,因为这实际上就是Awk自身做得很好的事情。

command which produces items |
awk '{ print "    - " $3 }'

当然,使用合理的近期GNU Coreutils split,你可以简单地做到

split --filter='printf "   - %s\n" "$FILE"'; cat >"$FILE" ... options