GNU Parallel 中的 basename

12

我有成百上千个文件,它们的名称如下:

RG1-t.txt

RG1-n.txt

RG2-t.txt

RG2-n.txt

等等...

我想使用GNU Parallel在这些文件上运行脚本,但我很难获取文件的basename,例如RG1、RG2等等,以便我可以运行以下命令:

ls RG*.txt | parallel "command.sh {basename}-t.txt {basename}-n.txt > {basename}.out"

导致产生文件RG1.out、RG2.out等。 有任何想法吗?

3个回答

23

使用内置的剥离选项

  1. Dirname ({/})和basename ({%}),并删除自定义后缀 ({^suffix})

    $ echo dir/file_1.txt.gz | parallel --plus echo {//} {/} {%_1.txt.gz}

  2. 获取basename,并删除最后 ({.}) 或任何 ({:}) 扩展名

    $ echo dir.d/file.txt.gz | parallel 'echo {.} {:} {/.} {/:}'

这应该可以满足您的需求:

ls RG*.txt | parallel "command.sh {.}-t.txt {.}-n.txt > {.}.out"

2
在并行计算中,20190422,{/}似乎是basename的等价物,而{//}则是dirname的等价物。 - Florian Castellane
1
给定输入字符串'foo/bar.baz',这些是替换后的字符串:{} => 'foo/bar.baz',{.} => 'foo/bar',{/} => 'bar.baz',{//} => 'foo',{/.}` => 'bar',截至20161222并行。 - forresthopkinsa
1
在20161222,为什么删除后缀不起作用呢?即parallel --plus echo '{%.bar.gz}' ::: foo.ext.bar.gz应该给我foo.ext,但它给我{%.bar.gz} foo.ext.bar.gz - Brian Wiley
2
好的,看起来这只适用于20161222之后的版本。我升级到了20201222(“疫苗”)。得爱并行计算的幽默感:0 - Brian Wiley

3
使用--rpl
printf '%s\0' RG*-n.txt |
  parallel -0 --rpl '{basename} s/-..txt$//' "command.sh {basename}-t.txt {basename}-n.txt > {basename}.out"

使用--plus进行动态替换字符串:

printf '%s\0' RG*-n.txt |
  parallel -0 --plus "command.sh {%-n.txt}-t.txt {} > {%-n.txt}.out"

printf的作用是避免:

bash: /bin/ls: Argument list too long

2

尝试像这样使用 parallel

ls RG*t.txt | cut -d'-' -f1 | parallel 'command.sh {}-t.txt {}-n.txt > {}.out'

或者,如果您更喜欢使用awk

ls RG*t.txt | awk -F'-' '{print $1}' | parallel ...

或者,如果您喜欢sed
ls RG*t.txt | sed 's/-.*//' | parallel ...

或者,如果你喜欢GNU grep:

ls RG* | grep -Po '.*(?=-t.txt)' | parallel ...

@forresthopkinsa,你不应该发表如此强烈的言论。有多种可能的解决方案。你批评的那个解决方案是完全可以接受的,也是最通用的(这就是为什么它在过去被接受的原因),因为它允许完全外部控制管道中传输的内容。其他下面的解决方案也同样完全可以接受。 - ATpoint
@ATpoint 在投票中似乎有一个普遍的共识,即下面的解决方案是更好的。我只评论了这个答案,因为它是被接受的答案,我想确保人们继续滚动。 - forresthopkinsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接