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

遍历目录中的文件,创建输出文件,linux,linux,bash,loops,bioinformatics,blast,Linux,Bash,Loops,Bioinformatics,Blast,我试图遍历特定目录(称为序列)中的每个文件,并对每个文件执行两个函数。我知道这些函数(blastp和cat行)可以工作,因为我可以在单个文件上运行它们。通常我会有一个特定的文件名作为查询、输出等,但我正试图使用一个变量,以便循环可以处理许多文件 (免责声明:我不熟悉编码。)我相信我在函数中使用文件名时遇到了严重的问题。实际上,我的代码将执行,但它会创建一堆额外的非预期文件。这就是我的脚本要做的: 第1行:遍历我的“sequences”目录中的每个文件。(如果有帮助的话,所有这些都以“.fa”结尾

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

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

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

第3行:将文件名识别为变量。(我知道,我知道,我认为我犯了可怕的错误。)

第4行:使用文件名作为“查询”标志的参数运行blastp函数,始终使用“database.faa”作为“db”标志的参数,并将结果输出到一个新文件中,该文件与初始文件同名,但结尾带有“.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
第5行:将第4行的部分输出文件输出到一个新文件中,该文件与初始文件具有相同的名称,但结尾带有“\u top\u 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\u top\u hits.txt”、“\u top\u hits.txt”、“\u top\u hits.txt.txt”和“\u top\u hits.txt”


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

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

用于序列中的序列/*.fa;
做

我可以向您提出以下改进:

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
我制作了更多中间变量,并(希望)使用有意义的名称。 我使用
\
来转义行尾,并允许在多行中放置命令。 我希望这能提高代码的可读性


我还没有测试。可能有输入错误。

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

mkdir 'folder_name'
然后需要将-o输出重定向到这些文件,类似这样

'command' -o /path/to/output/folder
为了帮助您测试这个脚本,您可以逐个运行每一行来测试它们。在合并之前,您需要确保每一行都能独立工作

最后一件事,使用冒号时要小心,它应该是这样的:

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

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