Bash:替换文件名的一部分

3

我有一个命令,想要在文件夹中的所有文件上运行,命令的语法如下:

tophat -o <output_file> <input_file>

我希望能够编写一个脚本,循环遍历任意文件夹中的所有文件,并使用输入文件名创建类似但不同的输出文件名。文件名如下:
input name                desired output name
path/to/sample1.fastq     path/to/sample1.bam
path/to/sample2.fastq     path/to/sample2.bam

让输入正常工作似乎很简单:

for f in *.fastq
do
     tophat -o <output_file> $f
done

我尝试使用output=${f,.fastq,.bam}作为输出参数,但是它不起作用。我只得到一个错误:line 3: ${f,.fastq,.bam}: bad substitution。这是我想要做的方式吗?还是应该做些其他的事情?如果这是正确的方法,那么我做错了什么?
[编辑]:
感谢所有的答案!但是有一个额外的问题...如果我的文件名像这样:
path/to/sample1_1.fastq
path/to/sample1_2.fastq
path/to/sample2_1.fastq
path/to/sample2_2.fastq
...

我需要处理的是一个任意数量的样本 (sampleX),每个样本都有两个相关联的文件 (_1_2)。现在的命令看起来像这样:

tophat -o <output_file> <input_1> <input_2>

因此,仍旧只有一个输出,我可以像这样做一些事情:"${f/_[1-2].fastq/.bam}",但我不确定如何得到一个循环,同时只对每个sampleX迭代一次并获取两个相关文件...... 有什么想法吗?

[编辑#2]:

因此,这是最终完成任务的脚本!

for f in *_1.fastq
do
        tophat -o "${f/_1.fastq/.bam}"  $f "${f/_1.fastq/_2.fasq}"
done
3个回答

4

您可以使用:

tophat -o "${f/.fastq/.bam}" "$f"

测试:

f='path/to/sample1.fastq'
echo "${f/.fastq/.bam}"
path/to/sample1.bam

非常感谢,解决了!总是有些小问题...你有什么想法来解决我编辑中的问题吗? - erikfas
你可以使用 "${f/_[0-9].fastq/.bam}" 来替换编辑部分。 - anubhava
如果您想要path/to/sample.bam作为最终输出,您也可以使用"${f/[0-9]_[0-9].fastq/.bam}" - anubhava
谢谢,那确实有效!我还找到了一个好的循环,将在原始帖子中进行编辑。 - erikfas

3

这不是答案,而是建议:作为一名生物信息学家,你应该使用GNU make及其选项-j(并行作业数)。Makefile应如下:

.PHONY:all
FASTQS=$(shell ls *.fastq)

%.bam: %.fastq
    tophat -o $@ $<

all:  $(FASTQS:.bam=.fastq)

1

除了anubhava简洁的解决方案之外,

d=$(dirname path/to/sample1.fastq)
b=$(basename path/to/sample1.fastq .fastq)
echo $d/$b.fastq
path/to/sample1.fastq

tophat -o "$d/$b.fastq" "$f"

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