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

3

我试图遍历特定目录(名为sequences)中的每个文件,并对每个文件执行两个函数。我知道这些函数('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"。
如果需要澄清任何信息,请告诉我。

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

3
如果您只对 *.fa 文件感兴趣,您可以像这样限制您的输入来匹配这些文件:

for sequence in sequences/*.fa; do


0

如果你只想要以 .fa 结尾的文件,那么你应该使用 *.fa。此外,如果你想将输出重定向到新文件夹中,你需要在某个地方创建这些目录。

mkdir 'folder_name'

那么你需要将-o输出重定向到这些文件中,类似于这样

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

为了帮助您测试这个脚本,您可以逐行运行来测试它们。在合并之前,您需要确保每一行都能正常工作。
最后一件事,注意使用冒号时要小心,应该像这样:
for filename in *.fa; do 'command'; done 

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

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

我还没有测试。可能会有拼写错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接