在多个文件上运行命令并为每个输出指定唯一的名称

在多个文件上运行命令并为每个输出指定唯一的名称

我想对文件夹中的所有文件运行一个脚本,如下所示:

sh script.sh *.fasta > output

但是我希望每个输入的输出都位于单独的文件中。因此,不是通过命令获取 5 个文件并将它们全部放入名为“output”的文件中,有没有一种方法可以让输出成为文件名,并在末尾添加后缀(如“_output”)?

所以如果我有 3 个文件,例如:

file1.fasta
file2.fasta
file3.fasta

有没有办法可以运行这样的命令:

sh script.sh *.fasta

并为每个输入输出这样的新文件:

file1_new.fasta
file2_new.fasta
file3_new.fasta

我尝试了命令:

sh script.sh *.fasta > *_output.fasta

但它不起作用,我还尝试将所有感兴趣的文件分配给这样的变量,他认为如果我首先将它们分配给变量,也许我可以以某种方式重命名输出:

allthefiles= *.fasta

但这也不起作用。我不知道该怎么称呼这个问题,如果已经被问过,很抱歉!如何通过命令运行多个文件并为每个输入提供新的输出?

答案1

for f in *.fasta; do 
    sh script.sh "$f" > "${f%.*}_output.fasta"; 
done

# ${f%.*} strips a shortest match of `.*` from the end of "$f"
# (= strips .fasta)

答案2

使用制作

编写一个名为的文件,GNUmakefile内容如下,但是我把字符 ↦ 放在哪里,就放一个制表符(必须是制表符,不能是空格)。

all: $(filter-out %_output.fasta,$(wildcard *.fasta))

%_output.fasta: %.fasta
↦./script.sh $< >[email protected]
↦mv [email protected] $@

现在,要重新生成所有文件,请键入make.作为奖励,如果输入文件自上次生成输出文件以来没有更改,script.sh则不会再次运行。如果您正在主动修改script.sh并且想要重新生成输出文件,请添加script.shafter %.fasta,这样如果脚本发生更改,文件也会重新生成。

说明:

  • 第一行指定运行时要执行的操作make all。因为这是第一行(第一行目标,在 makefile 术语中),make不带参数运行会做同样的事情。
  • 之后的部分all:生成当前目录中文件名的列表.fasta,并删除名为_output.fasta.
  • 该行%_output.fasta: %.fasta开始一个规则这解释了如何生成一个名称以_output.fasta目标)来自相应的.fasta文件(a依赖性)。
  • 以下制表符缩进行是生成文件所需运行的命令。
  • 第一行将第一个依赖项 ( $<) 转换为.tmp文件。
  • 第二行将.tmp文件重命名为目标文件 ( $@)。此两步过程的原因是,如果生成因任何原因中断,则不会留下无效的目标文件。

注意:我假设您使用的是 Linux。如果没有,make如果您想使用上面的代码,您可能需要安装 GNU make 并运行它,而不是系统的默认命令。

如果您对输出文件使用不同的扩展名,事情会变得更容易一些。

all: $(patsubst %.fasta,%.out,$(wildcard *.fasta))

.SUFFIX: .out .fasta
.fast.out:
↦./script.sh $< >[email protected]
↦mv [email protected] $@

如果用显式文件列表 ( all: foo.out bar.out) 替换第一行,则可以调用该文件Makefile并将其与make.

答案3

您可以使用 ... gnu parallel 并行执行它们:

parallel "sh script.sh {} > {}.out" ::: *

答案4

这是一个单行解决方案

find ./ -name "*.fasta" -exec sh -c 'script.sh ${0} > ${0}.log' {} \;

简而言之,它找到您想要的文件,并对它们执行脚本。使用的目的是不直接解释sh -c重定向字符。>

相关内容