首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用for循环在多个文件上运行zcat

使用for循环在多个文件上运行zcat
EN

Stack Overflow用户
提问于 2014-10-14 01:15:27
回答 2查看 9.6K关注 0票数 3

我对终端/bash非常陌生,也许以前有人问过这个问题,但我找不到我要找的东西,也许是因为我不确定应该搜索什么来回答我的问题。

我正在尝试格式化一些用于遗传分析的文件,虽然我可以为每个示例文件编写以下命令,但我知道有一个更好的方法:

代码语言:javascript
复制
zcat myfile.fastq.gz | awk 'NR % 8 == 5 || NR % 8 == 6 || NR % 8 == 7 || NR % 8 == 0 {print $0}' | gzip > myfile.2.fastq.gz
zcat myfile.fastq.gz | awk 'NR % 8 == 1 || NR % 8 == 2 || NR % 8 == 3 || NR % 8 == 4 {print $0}' | gzip > myfile.1.fastq.gz

我有以下文件:

代码语言:javascript
复制
-bash-3.2$ ls
BB001.fastq BB013.fastq.gz  IN014.fastq.gz  RV006.fastq.gz  SL083.fastq.gz
BB001.fastq.gz  BB014.fastq.gz  INA01.fastq.gz  RV007.fastq.gz  SL192.fastq.gz
BB003.fastq.gz  BB015.fastq.gz  INA02.fastq.gz  RV008.fastq.gz  SL218.fastq.gz
BB004.fastq.gz  IN001.fastq.gz  INA03.fastq.gz  RV009.fastq.gz  SL276.fastq.gz
BB006.fastq.gz  IN002.fastq.gz  INA04.fastq.gz  RV010.fastq.gz  SL277.fastq.gz
BB008.fastq.gz  IN007.fastq.gz  INA05.fastq.gz  RV011.fastq.gz  SL326.fastq.gz
BB009.fastq.gz  IN010.fastq.gz  INA1M.fastq.gz  RV012.fastq.gz  SL392.fastq.gz
BB010.fastq.gz  IN011.fastq.gz  RV003.fastq.gz  SL075.fastq.gz  SL393.fastq.gz
BB011.fastq.gz  IN012.fastq.gz  RV004.fastq.gz  SL080.fastq.gz  SL395.fastq.gz
BB012.fastq.gz  IN013.fastq.gz  RV005.fastq.gz  SL081.fastq.gz

我想将这两个zcat函数应用到每个文件中,从每个文件创建两个新文件,而不需要写出50次。我在R中使用了很多循环,但不知道从bash开始从哪里开始。我可以说出我想说的话,希望有人能帮我编写代码!

代码语言:javascript
复制
for FILENAME.fastq.gz in all files in cd

zcat FILENAME.fastq.gz | awk 'NR % 8 == 5 || NR % 8 == 6 || NR % 8 == 7 || NR % 8 == 0 {print $0}' | gzip > FILENAME.2.fastq.gz
zcat FILENAME.fastq.gz | awk 'NR % 8 == 1 || NR % 8 == 2 || NR % 8 == 3 || NR % 8 == 4 {print $0}' | gzip > FILENAME.1.fastq.gz

提前谢谢你的帮助!

编辑*

我的表示法有点偏离,这是最后的,正确的循环:

代码语言:javascript
复制
for fname in *.fastq.gz
do
    gzcat "$fname" | awk 'NR % 8 == 5 || NR % 8 == 6 || NR % 8 == 7 || NR % 8 == 0 {print $0}' | gzip >../../SeparateReads/"${fname%.fastq.gz}.2.fastq.gz"
    gzcat "$fname" | awk 'NR % 8 == 1 || NR % 8 == 2 || NR % 8 == 3 || NR % 8 == 4 {print $0}' | gzip >../../SeparateReads/"${fname%.fastq.gz}.1.fastq.gz"
done

问题*

当我运行以下命令时:

代码语言:javascript
复制
for fname in *.1.fastq.gz
do
cat ./CleanedSeparate/XhoI/"$fname" ./CleanedSeparate/MseI/"${fname%.1.fastq.gz}.2.fastq.gz" > ./FinalCleaned/"${fname%.1.fastq.gz}.fastq.gz"
done

我知道这个错误:

代码语言:javascript
复制
cat: ./CleanedSeparate/XhoI/*.1.fastq.gz: No such file or directory
cat: ./CleanedSeparate/MseI/*.2.fastq.gz: No such file or directory

显然,我没有正确使用*。关于我哪里出错有什么建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-14 01:24:42

代码语言:javascript
复制
for fname in *.fastq.gz
do
    zcat "$fname" | awk 'NR % 8 == 5 || NR % 8 == 6 || NR % 8 == 7 || NR % 8 == 0 {print $0}' | gzip >"${fname%.fastq.gz}.2.fastq.gz"
    zcat "$fname" | awk 'NR % 8 == 1 || NR % 8 == 2 || NR % 8 == 3 || NR % 8 == 4 {print $0}' | gzip >"${fname%.fastq.gz}.1.fastq.gz"
done

要点:

  • for fname in *.fastq.gz 这将遍历当前目录中以.fastq.gz结尾的每个文件。如果文件位于不同的目录中,则使用: 用于/path/to/*.Quickq.gz中的fname 无论到达这些文件的路径是什么,/path/to/都在哪里。
  • zcat "$fname" 这部分很简单。它在文件名中替换为zcat的参数。
  • "${fname%.fastq.gz}.1.fastq.gz" 这有点棘手。要获得所需的输出文件名,需要将.1插入到原始文件名中。在bash中做到这一点的最简单的方法是从带有${fname%.fastq.gz}的文件名中删除%后缀(%是bash),意思是从末尾删除后面的内容。然后,添加新的后缀.1.fastq.gz,并具有正确的文件名。

在另一个目录中创建新文件

根据后续问题,这是行不通的:

代码语言:javascript
复制
for fname in *.1.fastq.gz
do
    cat ./CleanedSeparate/XhoI/"$fname" ./CleanedSeparate/MseI/"${fname%.1.fastq.gz}.2.fastq.gz" > ./FinalCleaned/"${fname%.1.fastq.gz}.fastq.gz"
done

问题是,在for语句中,shell正在当前目录中查找*.1.fastq.gz。但是,他们不在那里。他们在./CleanedSeparate/XhoI/。相反,运行:

代码语言:javascript
复制
dir1=./CleanedSeparate/XhoI
for fname in "$dir1"/*.1.fastq.gz
do
    base=${fname#$dir1/}
    base=${base%.1.fastq.gz}
    echo "base=$base"
    cat "$fname" "./CleanedSeparate/MseI/${base}.2.fastq.gz" >"./FinalCleaned/${base}.fastq.gz"
done

请注意,for语句被赋予了正确的目录来查找文件。

票数 5
EN

Stack Overflow用户

发布于 2014-10-14 01:25:16

您可以使用以下内容:

代码语言:javascript
复制
for fspec in *.fastq.gz ; do
    echo "${fspec}"
done

这将简单地回显正在处理的文件,但您可以执行任何想要${fspec}的操作,包括将它用于几个zcat命令。

为了获取文件名的根(用于创建其他文件),您可以使用bash的模式删除特性来删除尾随位:

代码语言:javascript
复制
for fspec in *.fastq.gz ; do
    froot=${fspec%%.fastq.gz}
    echo "Transform ${froot}.fastq.gz into ${froot}.1.fastq.gz"
done

此外,根据您的特定需要,您似乎希望将一个八行组的前四行发送到一个文件,而将其他四行发送到另一个文件。

我倾向于将sed用于类似这样的简单任务,因为它可能会更快。您可以使用以下方法获得第一行组(八行中的前四行):

代码语言:javascript
复制
sed -n 'p;n;p;n;p;n;p;n;n;n;n'

第二行(八行中的后四行):

代码语言:javascript
复制
sed -n 'n;n;n;n;p;n;p;n;p;n;p'

使用p打印当前和n获取下一个命令。

因此,代码就变成了这样的东西:

代码语言:javascript
复制
for fsrc in *.fastq.gz ; do
    fdst1="${fspec%%.fastq.gz}.1.fastq.gz"
    fdst2="${fspec%%.fastq.gz}.2.fastq.gz"
    echo "Processing ${fsrc}"

    # For each group of 8 lines, fdst1 gets 1-4, fdst2 gets 5-8.
    zcat ${fsrc} | sed -n 'p;n;p;n;p;n;p;n;n;n;n' | gzip >${fdst1}
    zcat ${fsrc} | sed -n 'n;n;n;n;p;n;p;n;p;n;p' | gzip >${fdst2}
done
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26351242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档