我对终端/ bash很新,也许以前曾经问过这个问题但是我找不到我想要的东西也许是因为我不确定搜索什么来回答我的问题。
我试图格式化一些文件进行遗传分析,而我可以为每个样本文件写出以下命令,我知道有更好的方法:
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
我有以下文件:
-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。我可以用文字说出我想要的东西,希望有人能给我一个编码的手!:
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
提前感谢您的帮助!
***** EDIT *****
我的符号有点偏差,这是最后的,正确的循环:
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
*****关注问题*****
当我运行以下内容时:
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
我收到此错误:
cat: ./CleanedSeparate/XhoI/*.1.fastq.gz: No such file or directory
cat: ./CleanedSeparate/MseI/*.2.fastq.gz: No such file or directory
显然我没有正确使用*。关于我哪里出错的任何提示?
答案 0 :(得分:3)
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
结尾的当前目录中的每个文件。如果文件位于不同的目录中,请使用:
for fname in /path/to/*.fastq.gz
其中/path/to/
是获取这些文件的路径。
zcat "$fname"
这部分很简单。它将文件名替换为zcat
。
"${fname%.fastq.gz}.1.fastq.gz"
这有点棘手。要获取所需的输出文件名,我们需要将.1
插入原始文件名。在bash
中执行此操作的最简单方法是使用.fastq.gz
从文件名中删除${fname%.fastq.gz}
后缀,其中%
是bash-speaking含义从最后删除。然后,我们添加新的后缀.1.fastq.gz
,我们有正确的文件名。
根据后续问题,这不起作用:
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/
。相反,运行:
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
语句被赋予了查找文件的正确目录。
答案 1 :(得分:0)
您可以使用以下内容:
for fspec in *.fastq.gz ; do
echo "${fspec}"
done
这只会回显正在处理的文件,但您可以执行${fspec}
所需的任何操作,包括将其用于几个zcat
命令。
为了获取文件名的 root (用于创建其他文件),可以使用bash
的模式删除功能删除尾随位:
for fspec in *.fastq.gz ; do
froot=${fspec%%.fastq.gz}
echo "Transform ${froot}.fastq.gz into ${froot}.1.fastq.gz"
done
此外,对于特定的需要,您似乎希望将八行组的前四行发送到一个文件,将另外四行发送到第二个文件。
我倾向于只使用sed
来完成这样的简单任务,因为它可能更快。您可以通过以下方式获取第一个线组(八个线中的前四个线):
sed -n 'p;n;p;n;p;n;p;n;n;n;n'
和第二个(八个中的第二个四行):
sed -n 'n;n;n;n;p;n;p;n;p;n;p'
使用p
print-current和n
get-next命令。
因此代码就变成了:
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