4

我在使用 GNU 并行( http://www.gnu.org/software/parallel/)时遇到大括号(大括号)问题

我有四个文件的列表:

file1.txt.super
file2.txt.super
file3.txt.super
file4.txt.super

如果我发出:ls * | parallel "mkdir ./{.}"

我返回了四个目录:

file1.txt
file2.txt
file3.txt
file4.txt

我的问题是,我怎样才能简单地返回四个名为:

file1
file2
file3
file4

我已阅读http://www.linuxjournal.com/article/8919但无法使用 gnu 并行实现这些正则表达式。我想我在这里遗漏了一些东西。此外,非常感谢任何具有更复杂正则表达式的示例。

4

6 回答 6

6

是的,您似乎在这里遗漏了一些东西linuxjournal文章解释了 shell 参数扩展的特性。这些大括号(总是以 开头)与实用程序的默认替换字符串$无关,它们巧合地使用大括号。并行文档显示命令行选项允许使用任意字符串而不是用大括号括起来的默认值。parallel

例如,您示例中的替换字符串 {.}可以更改为%foo

ls * | parallel --extensionreplace %foo "mkdir ./%foo"

更多关于${…}linuxjournal 文章的信息可以在man bash页面的 参数扩展部分找到。

由于您在@AdamLiss 答案的评论中提出了要求,因此这是一种(ab)使用花括号--colsep参数来执行任务的方法:

ls * | parallel --colsep '\.' "mkdir ./{1}"

注意:如果文件名包含两个以上的句点(因为路径名在第一个句点被截断,则此--colsep 技巧(如sed@AdamLiss 提出的)将产生不良结果。)

然而,由于--colsep参数是一个正则表达式,这应该对文件名中其他地方的句点有弹性:

ls * | parallel --colsep '\.[^\.]*$' "mkdir ./{1.}"

注意:--extensionreplace由于当前 (21120422) 并行版本中的错误,无法正常工作。但由于parallel是一个 perl 脚本,您可以通过更改来修复它:

    "extensionreplace|er" => \$::opt_U,

    "extensionreplace|er=s" => \$::opt_U,
于 2012-04-25T04:20:08.700 回答
3

如果您不介意使用sed,这里有一个解决方法:

ls * | sed 's/\..*//' | parallel "mkdir ./{}"
于 2012-04-20T00:45:00.673 回答
2

这可能对您有用:

ls * | parallel echo {.} | parallel mkdir {.}
于 2012-04-24T18:55:51.140 回答
1

我不明白“.super”是什么,或者当你并行运行时它的去向,或者在并行命令中使用“{.}”。AFAIK,并行工作像 xargs 并且只理解{}. 我错过了什么?

在任何情况下,我都会通过 for 循环实现目标:

for f in *; do mkdir "${f%%.*}"; done

或者,如果您真的关心这么短的作业的并行性:

for f in *; do mkdir "${f%%.*}" & done
于 2012-04-22T23:44:20.593 回答
1

根据手册页中的示例,以下应该可以工作,即使它不是很漂亮:

ls *.txt.super| parallel --er {txt} 'echo {txt}|parallel "mkdir ./{.}"'

删除第二个文件扩展名是通过从 parallel 中调用 parallel 并将{.}字符串别名到parallel{txt}的父实例中来完成的。

于 2012-04-23T00:13:58.010 回答
1

除了这里已经很好的答案之外,我很确定最简单的解决方案(可能是@Steve 正在寻找的)如下:

ls * | parallel --plus mkdir {..}

gnu parallel中的{.} 替换字符串旨在将字符串“修剪”到最外面的字符。我相信您可以将字符串修剪到 3 个级别。..

这意味着{.}将仅削减一级至file1.txt{..}将削减两级至file1{...}并将削减第三级。

于 2021-02-18T15:41:05.300 回答