管道输出从命令到另一个命令

Pipe output from command to another command

bash 函数 prepend_line 有两个参数:一个字符串和一个文件的完全限定路径。它用于记录,插入当前 date/time 和日志文件顶部的字符串。

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

如何获取命令的输出,例如mv -fv "$fileOne" "$fileTwo" 用作 prepend_line?

的第一个参数

我已经尝试了各种管道组合到 xargs,但我不明白它是如何工作的,而且我不相信它是无论如何最好的方法。

如果你真的需要:

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

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

测试:

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 "" "$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 "" command to the log_file
    <<<"" xxd -p -r >> ""

    # 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 内部,我只是将输出重定向到日志文件或一些临时文件,省去了解析和特殊情况的需要。