我喜欢 GNU parallel
,但我发现执行字符串替换相当复杂。
我习惯于在 Bash 中进行简单的操作:
$ f="encodes/TearsOfSteel-720-crf41.mp4"
$ echo "$(basename "${f%%-*}")"
TearsOfSteel
基本上,我想找到每个输入文件的基本名称(第一个减号连字符之前的所有内容)。然后parallel
,我想使用原始文件名和基本名称执行命令:
parallel './do_something {} <basename>' ::: encodes/*.mp4
…<basename>
如果您给了 Bash 什么basename "${f%%-*}"
,它会做什么,f
显然是{}
。
非平行版本如下:
for f in encodes/*.mp4; do
bn="$(basename "${f%%-*}")"
./do_something "$f" "$bn"
done
我怎样才能做到这一点parallel
?
答案1
如果你经常这样做,请通过以下方式定义自己的替换字符串~/.parallel/config
:
--rpl '{_} s:.*/::; s:-.*::;'
然后你可以这样做:
parallel ./do_something {} {_} ::: encodes/*.mp4
还要记住,您可以定义一个bash
函数并调用它:
doit() {
f="$1"
bn="$(basename "${f%%-*}")"
./do_something "$f" "$bn"
}
export -f doit
parallel doit {} ::: encodes/*.mp4
答案2
我还没有找到一种简单的方法来进行 Bash 风格的操作,但你可以使用perl
表达式来执行字符串替换。随后删除不需要的字符串部分非常简单。
其中一种方法是:
parallel "./do_something {} {= s:.*\/::; s:-.*:: =}" ::: encodes/*.mp4
这是如何运作的?
你可以perl
在里面运行命令parallel
使用{= … =}
。使用perl
,您可以使用以下表达式删除文件夹名称:
s/.*\///
这意味着:将第一个斜杠之前的所有内容替换为空。我们可以将分隔符从 替换为 ,/
以:
使其更具可读性(s:.*\/::
)。
您可以对尾随部分执行相同操作,即删除从第一个减号连字符开始的所有内容,如下所示:
s:-.*::
整个命令是这两个替换的组合,以分号分隔。然后命令变为:
{= s:.*\/::; s:-.*:: =}