遍历目录中的文件,创建输出文件,linux

时间:2016-11-23 03:21:47

标签: linux bash loops bioinformatics blast

我试图遍历特定目录中的每个文件(称为序列),并在每个文件上执行两个函数。我知道函数('blastp'和'cat'行)可以工作,因为我可以在单个文件上运行它们。通常我会有一个特定的文件名作为查询,输出等,但我正在尝试使用一个变量,因此循环可以处理许多文件。

(免责声明:我是编码的新手。)我相信我在尝试在我的函数中使用我的文件名时遇到了严重的问题。实际上,我的代码将执行,但它会创建一堆额外的非预期文件。这就是我打算让我的脚本做的事情:

第1行:遍历“sequences”目录中的每个文件。 (所有这些都以“.fa”结尾,如果这有用的话。)

第3行:将文件名识别为变量。 (我知道,我知道,我认为我做错了。)

第4行:使用文件名作为“query”标志的参数运行blastp函数,始终使用“database.faa”作为“db”标志的参数,并将结果输出到新文件中与初始文件具有相同的名称,但最后使用“.txt”。

第5行:将第4行输出文件的部分输出到一个新文件中,该文件与初始文件同名,但最后带有“_top_hits.txt”。

for sequence in ./sequences/{.,}*;
    do
            echo "$sequence";
            blastp -query $sequence -db database.faa -out ${sequence}.txt -evalue 1e-10 -outfmt 7
            cat ${sequence}.txt | awk '/hits found/{getline;print}' | grep -v "#">${sequence}_top_hits.txt
    done

当我运行这段代码时,它给了我六个从目录中的每个文件派生的新文件(它们都在同一个目录中 - 我更喜欢将它们全部放在自己的文件夹中。我怎么能这样做?)。他们都是空的。它们的后缀是“.txt”,“。txt.txt”,“。txt_top_hits.txt”,“_ top_hits.txt”,“_ top_hits.txt.txt”和“_top_hits.txt_top_hits.txt”。

如果我可以提供任何进一步的信息以澄清任何事情,请告诉我。

3 个答案:

答案 0 :(得分:3)

如果您只对START_STICKY文件感兴趣,我会将您的输入限制为仅限于以下匹配文件:

*.fa

答案 1 :(得分:0)

我可以为您提出以下改进建议:

for fasta_file in ./sequences/*.fa # ";" is not necessary if you already have a new line for your "do"
do
    # ${variable%something} is the part of $variable
    # before the string "something"
    # basename path/to/file is the name of the file
    # without the full path
    # $(some command) allows you to use the result of the command as a string
    # Combining the above, we can form a string based on our fasta file
    # This string can be useful to name stuff in a clean manner later
    sequence_name=$(basename ${fasta_file%.fa})
    echo ${sequence_name}
    # Create a directory for the results for this sequence
    # -p option avoids a failure in case the directory already exists
    mkdir -p ${sequence_name}
    # Define the name of the file for the results
    # (including our previously created directory in its path)
    blast_results=${sequence_name}/${sequence_name}_blast.txt
    blastp -query ${fasta_file} -db database.faa \
        -out ${blast_results} \
        -evalue 1e-10 -outfmt 7
    # Define a file name for the top hits
    top_hits=${sequence_name}/${sequence_name}_top_hits.txt
    # alternatively, using "%"
    #top_hits=${blast_results%_blast.txt}_top_hits.txt
    # No need to cat: awk can take a file as argument
    awk '/hits found/{getline;print}' ${blast_results} \
        | grep -v "#" > ${sequence_name}_top_hits.txt
done

我制作了更多的中间变量,(希望)有意义的名字。 我使用\来转义行结束并允许将命令放在几行中。 我希望这可以提高代码的可读性。

我还没有接受过测试。可能存在拼写错误。

答案 2 :(得分:0)

如果只需要以.fa结尾的文件,则应该使用*.fa。此外,如果要将输出重定向到新文件夹,则需要使用

mkdir 'folder_name'

然后,您需要将-o输出重定向到这些文件,例如

'command' -o /path/to/output/folder

为帮助您测试此脚本,可以逐行运行每一行对其进行测试。您需要确保每行在合并之前都能独立工作。

最后一件事,请谨慎使用冒号,它应类似于以下内容:

for filename in *.fa; do 'command'; done