我想对文件夹中的所有文件运行一个脚本,如下所示:
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.sh
after %.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
重定向字符。>