【问题标题】:Iterate through files in a directory, create output files, linux遍历目录中的文件,创建输出文件,linux
【发布时间】:2016-11-23 03:21:46
【问题描述】:

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

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

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

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

第 4 行:使用文件名作为“query”标志的参数运行 blastp 函数,始终使用“database.faa”作为“db”标志的参数,并将结果输出到一个新文件中is 与初始文件同名,但以“.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”。

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

【问题讨论】:

  • 看起来至少您的一个问题是您尝试在同一个目录中多次运行同一个函数。每次运行它时,我相信您的循环会找到您在先前运行中生成的新文件并尝试对它们进行操作。据我所知,您并没有将文件搜索限制为以*.fa 结尾的文件,但我建议您这样做。否则,您将继续处理新输出的 .txt 文件并生成更多错误输出。
  • 我同意,我确实需要这样做。我想解决这个问题的另一种方法是将我的所有输出文件输出到一个单独的目录。我如何让它只遍历以 *.fa 结尾的文件?我要把它放在第 1 行吗?

标签: linux bash loops bioinformatics blast


【解决方案1】:

如果您只对 *.fa 文件感兴趣,我会将您的输入限制为仅匹配这样的文件:

for sequence in sequences/*.fa; do

【讨论】:

    【解决方案2】:

    我可以建议您进行以下改进:

    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
    

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

    我没有测试过。可能有错别字。

    【讨论】:

      【解决方案3】:

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

      在某处创建这些目录
      mkdir 'folder_name'
      

      然后你需要将你的 -o 输出重定向到这些文件,像这样

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

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

      最后一件事,小心使用冒号,它应该看起来像这样:

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

      【讨论】:

        猜你喜欢
        • 2010-12-16
        • 1970-01-01
        • 2021-12-06
        • 2023-03-16
        • 1970-01-01
        • 2017-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多