Bash: 在函数中使用 xargs/parallel 个参数进行变量替换

Bash: using xargs/parallel arguments in function for variable substituion

我已经为这个 Bash 脚本苦苦挣扎了大约一个星期,试图做看起来最简单的事情。我正在使用 fswatch 来监视给定的文件夹并生成添加到其中的任何单个文件的文件名作为输出。该输出通过管道传输到 xargs,然后 运行 是一个包含多个命令的函数,这些命令使用 fswatch/xargs 传递的文件名并进行 variable/argument 替换。

#!/bin/bash

compressor() {
    filepath="filepath"
    mkdir -m 777 /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING
    mv ${filepath} /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath##/} -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath%.*}.mp4
}

export -f compressor

/usr/local/Cellar/fswatch/1.8.0/bin/fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch |
    xargs -0 -n1 -I'filepath' bash -c compressor 'filepath'

在最简单的配置中,我将输出通过管道传输到 xargs 并使用 xargs 到 运行 一个使用参数替换的程序,一切正常。然后我收到一个请求,让脚本为每个添加的文件创建一个新文件夹,将文件移动到该文件夹​​,然后 运行 命令。

使用多个命令似乎没有任何效果。我无法让 xargs 将参数传递给函数,以便函数可以使用参数定义变量并在文件路径中进行变量替换。如果我在函数中执行 xargs -I'filepath' command 'filepath' 然后 filepath="filepath",我最终会 mkdir 创建一个名为 filepath_PROCESSING 的文件,而不是 fswatch 中的参数被替换.

如何使用 xargs 将参数传递给函数?

两件事:你误会了how function arguments are passed。它们是位置参数(例如 1、2、3 等),因此您的函数可以这样定义:

compressor() {
    filepath=""
    # define a variable rather than including this 5 times
    process="/Users/lr/Desktop/Watch/${filepath#/}_PROCESSING"
    mkdir -m 777 "$process"
    mv "$filepath" "$process"
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath "$process/${filepath#/}" -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath "$process/${filepath%.*}.mp4"
}

然后,当您调用 bash -c 时,它需要一个参数(请参阅下面的注释),但您将其传递给两个参数。尝试一些引号,它应该有效:

fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch |
    xargs -0 -n1 -I filepath bash -c 'compressor "filepath"'

[-c will] read and execute commands from the first non-option argument after processing the options, then exit. Any remaining arguments are assigned to the positional parameters, starting with [=15=].

Bash Reference Manual, Invoking Bash

显然我无法复制您的设置,但是 an MVCE 在 bash 版本 3 和 4 中对我来说效果很好:

#!/bin/bash    
make_noise() {
    echo "" "" "" ""
}
export -f make_noise
echo "foo bar" | xargs -I {} bash -c "make_noise '{}'"

尝试:

#!/bin/bash

compressor() {
    filepath=""
    mkdir -m 777 /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING
    mv ${filepath} /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath##/} -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath%.*}.mp4
}

export -f compressor

/usr/local/Cellar/fswatch/1.8.0/bin/fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch |
    parallel -0 compressor