在 GNU parallel 中执行类似 bash 的字符串操作

在 GNU parallel 中执行类似 bash 的字符串操作

我喜欢 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:-.*:: =}

相关内容