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

Iterate through files in a directory, create output files, linux

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

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

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

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

第 4 行:运行 blastp 函数使用文件名作为 "query" 标志的参数,始终使用 "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".

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

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

for sequence in sequences/*.fa; do

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

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