将输出从命令传递到另一个命令

时间:2019-06-26 16:30:18

标签: bash xargs

bash函数prepend_line具有两个参数:字符串和文件的全限定路径。用于记录日志,在日志文件的顶部插入当前日期/时间和字符串。

独立使用效果很好:prepend_line "test string" "$log_file"

如何从命令获取输出,例如mv -fv "$fileOne" "$fileTwo"用作prepend_line的第一个参数?

我已经尝试过各种组合到xargs的管道,但是我不知道它是如何工作的,我也不相信这是在任何情况下的最佳方法。

1 个答案:

答案 0 :(得分:1)

如果您确实需要:

export -f prepend_line
mv -fv "$fileOne" "$fileTwo" |
xargs -0 bash -c 'prepend_line "$1" "$log_file"' --

-0将行解析为蜂鸣式零分隔。由于mv -v输出中不应有零,因为文件名不能有零字节,所以您只会得到一个元素。该元素/行将作为第一个参数传递给bash子外壳。

经过测试:

prepend_line() {
  printf "%s\n" "$@" | xxd -p
}

fileOne=$'1\x01\x02\x031234566\n\t\e'
fileTwo=$'2\x01\x02\x031234566\n\t\e \n\n\n'
export -f prepend_line

printf "%s\n" "$fileOne -> $fileTwo" |
xargs -0 bash -c 'prepend_line "$1" "$log_file"' --

脚本将输出(从xxd -p内部的prepend_line输出):

31010203313233343536360a091b202d3e2032010203313233343536360a
091b200a0a0a0a0a0a

相同的十六进制输出,带有一些额外的换行符和注释:

# first filename $'1\x01\x02\x031234566\n\t\e'
31010203313233343536360a091b
# the string: space + '->' + space
202d3e20
# second filename $'2\x01\x02\x031234566\n\t\e \n\n\n'
32010203313233343536360a091b200a0a0a0a0a0a

如果确实需要解析一些奇怪的输入,则可以使用xxd -p将字符串转换为十六进制。然后,稍后用xxd -r -p将其转换回机器表示,并直接流到输出中:

prepend_line() {
    # some work

    # append the output of the "$1" command to the log_file
    <<<"$1" xxd -p -r >> "$2"

    # some other work
}

prepend_line "$(mv -fv "$fileOne" "$fileTwo" | xxd -p)" "$log_file"

但我怀疑您是否将需要处理此类案件。谁使用$'\x01'命名文件名并使用空换行符'great_script.sh'$'\n\n'后缀?

无论如何,客观地讲,我希望界面使用流:

 mv -fv "$fileOne" "$fileTwo" | prepend_line "$log_file"

它需要set -o pipefail才能正确传播错误。在prepend_line内部,我将输出重定向到日志文件或某些临时文件,从而避免了解析和极端情况的需要。