我是shell脚本的新手,我一整天都在努力弄清楚如何执行“for”命令。基本上,我想要做的是以下几点:
我有一个带有一堆名字的list.txt文件:
name1
name2
name3
对于列表中的每个名称,有两个不同的文件,每个文件都有不同的名称结尾。例如:
name1_R1
name1_R2
我尝试运行的程序名为sickle
。基本上,它需要两个文件(彼此对应)并对它们进行分析,因此需要我有这个命名方案。镰刀命令如下:
sickle pe -f input_file1.fastq -r input_file2.fastq -t sanger \
如果有人可以帮助我,至少只是告诉我如何让unix读取文件列表并独立处理每一行,我想我可以从那里开始。我尝试了一些东西,但没有一个能奏效。
答案 0 :(得分:12)
有几种方法可以做到这一点。由于数据文件中的名称是“每行一个”,我们可以假设文件名中没有换行符。
for
循环for file in $(<list.txt)
do
sickle pe -f "${file}_file1.fastq" -r "${file}_file2.fastq" -t sanger
done
while
循环read
while read file
do
sickle pe -f "${file}_file1.fastq" -r "${file}_file2.fastq" -t sanger
done < list.txt
for
循环仅在名称中没有空格(或其他空白字符,如制表符)时才有效。只要名称中没有换行符,while
循环就是干净的,尽管使用while read -r file
可以更好地防范意外情况。 for
循环中文件名周围的双引号是装饰性的(但无害),因为文件名不能包含空格,但while
循环中的文件名阻止包含空格的文件名在它们应该被分割时不要拆分。每次使用变量时引用变量通常都是一个好主意,尽管严格来说只有当变量可能包含空格但你不希望值分开时才会很重要。
我不得不猜测应该将哪些名称传递给sickle
命令,因为你的问题不清楚 - 我99%肯定我猜错了,但它匹配不同的后缀假设文件的基本名称为input
的示例命令。我省略了尾随反斜杠;它是“逃避”角色,目前尚不清楚你真正想要的是什么。
答案 1 :(得分:4)
Bash有一个非常合理的for循环作为其looping constructs之一。您可以使用所需的任何自定义命令替换下面的echo命令。例如:
for file in name1 name2 name3; do
echo "${file}_R1" "${file}_R2"
done
这个想法是循环将每个文件名分配给 file 变量,然后将_R1和_R2后缀附加到它们。请注意,引用可能很重要,如果不需要则不会造成伤害,因此您应该将其用作防御性编程措施。
如果你想从文件中读取而不是直接使用for循环,你可以使用Bash的read builtin,但 xargs 通常在shell中更容易移植。例如,以下使用来自GNU findutils的 xargs 版本中可用的标志来读取文件中的参数,然后为每个文件添加后缀:
$ xargs --arg-file=list.txt --max-args=1 -I{} /bin/echo "{}_R1" "{}_R2"
name1_R1 name1_R2
name2_R1 name2_R2
name3_R1 name3_R2
同样,您可以使用您选择的命令行替换“echo”。
答案 2 :(得分:2)
使用while
循环read
:
while read fn; do
<command> "${fn}_R1" "${fn}_R2"
done < list.txt