如何使用 xargs 或并行在路径中使用 * 连接多个文件

如何使用 xargs 或并行在路径中使用 * 连接多个文件

我有一个命令可以获取 CSV 文件中每一行的文件路径:

awk -F, 'NR>0 {print "/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/" $2 "_*/dragen-covidseq/" $1 "_*_ds*/consensus/*.consensus_hard_masked_sequence.fa"}' input.csv

input.csv 文件示例:

2071404446,RUN111
2071405093,RUN111
2071405134,RUN111

此命令后的详细示例:

/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071404446_*_ds*/consensus/*.consensus_hard_masked_sequence.fa
/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071405093_*_ds*/consensus/*.consensus_hard_masked_sequence.fa
/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071405134_*_ds*/consensus/*.consensus_hard_masked_sequence.fa

现在我想将不同文件的所有内容连接到一个文件中。我尝试了简单的管道命令,例如:

awk -F, 'NR>0 {print "/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/" $2 "_*/dragen-covidseq/" $1 "_*_ds*/consensus/*.consensus_hard_masked_sequence.fa"}' input.csv | xargs cat > output.fasta

但我有“没有这样的文件或目录”错误,因为它似乎xargs解释*为字符而不是通配符。作为信息,除了 之外 *,我的路径中没有空间或任何空间字符。

你知道该怎么做吗?

答案1

如果您想将这些*字符扩展为 shell 全局字符(通配符),您必须将它们传递给执行此操作的程序,例如 shell。

假设输入文件的字段不包含其他对 shell 有特殊含义的字符,可以尝试(1):

awk -F, 'NR>0 {print "cat /mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/" $2 "_*/dragen-covidseq/" $1 "_*_ds*/consensus/*.consensus_hard_masked_sequence.fa"}' input.csv | sh > output.fasta

awk命令会打印类似这样的命令,这些命令cat /path/with/wildcards/to/some/file会通过管道传输到 shell 进行解释。如果想避免cat为每个文件运行单独的进程,可以让 shell 打印文件名并将其传递给xargs(2):

awk -F, 'NR>0 {print "echo /mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/" $2 "_*/dragen-covidseq/" $1 "_*_ds*/consensus/*.consensus_hard_masked_sequence.fa"}' input.csv | sh | xargs cat > output.fasta

当我awk使用问题中所示的输入文件从 (1) 运行命令时,命令的输出awk

cat /mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071404446_*_ds*/consensus/*.consensus_hard_masked_sequence.fa
cat /mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071405093_*_ds*/consensus/*.consensus_hard_masked_sequence.fa
cat /mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/RUN111_*/dragen-covidseq/2071405134_*_ds*/consensus/*.consensus_hard_masked_sequence.fa

请注意,输出行以cat(与awk问题中的命令相反)。

我无法测试 shell 对字符的扩展,*因为我没有任何与该模式匹配的文件。

(2) 中的命令awk将创建类似的输出,但用echo代替cat

答案2

只要其中没有特殊的 shell 字符$base$fa_pattern这应该可以工作:

base=/mnt/datagenetique/ANALYSIS/Infectiologie/COVID-WGS/Analyse/
fa_pattern=_*_ds*/consensus/*.consensus_hard_masked_sequence.fa

# Generate one file per pattern
cat input.csv |
  parallel --colsep , eval cat $base/{2}_*/dragen-covidseq/{1}$fa_pattern '>' {1}.fa

# Put everything in a single file
cat input.csv |
  parallel --colsep , eval cat $base/{2}_*/dragen-covidseq/{1}$fa_pattern > all.fa

# This may be faster
cat input.csv |
  parallel --colsep , -uj1 eval cat $base/{2}_*/dragen-covidseq/{1}$fa_pattern > all2.fa

答案3

当然,让 shell 解释输入数据的风险由您自己承担,但这就是您需要帮助的原因:

$ echo first > foolbar
$ echo second > foo\*bar

$ cat $(awk 'BEGIN{print "foo*bar"}')
second
first

上面假设参数列表为cat不会超过 shell 最大参数长度,请参阅https://stackoverflow.com/a/4185165/1745001。或者:

$ while IFS= read -r file; do cat $file; done < <(awk 'BEGIN{print "foo*bar"}')
second
first

相关内容