UNIX 如何使用输入文件的基础作为输出文件的一部分

UNIX how to use the base of an input file as part of an output file

我很少使用 UNIX,所以如果这个问题看起来很简单,我深表歉意。我试图遍历子目录和文件,然后从循环抓取的特定文件生成输出,然后将输出通过管道传输到另一个目录中的文件,该文件的名称可以从输入文件中识别出来。到目前为止我有:

 for file in /home/sub_directory1/samples/SSTC*/ 
      do
           samtools depth -r chr9:218026635-21994999 < $file > /home/sub_directory_2/level_2/${file}_out
      done

我希望在 sub_directory1/samples/SSTC*/ 中从 file_1_novoalign.bam 生成输出并将该输出作为名为 file_1_novoalign_out.bam 的输出文件发送到 /home/sub_directory_2/level_2/ 但是它不起作用 - 它说 'bash: /home/sub_directory_2/level_2/file_1_novoalign.bam.out: No such file or directory'。

理想情况下,我希望能够删除输出文件的“_novoalign.bam”部分并替换为“_out.txt”。我相信这对于普通的 unix 用户来说很容易,但我已经搜索过但找不到快速的答案,而且真的没有时间花很长时间搜索。在此先感谢您根据我目前的代码提出的任何建议,或者欢迎提出任何替代建议。

p.s。我没有权限将文件写入包含输入文件夹的目录

下面是对不带空格的文件名的解释,保持简单。
当您需要文件而不是目录时,您应该以 * 而不是 */ 结束 for 循环。 当你只想处理以 _novoalign.bam 结尾的文件时,你应该告诉 unix。 最简单的方法是使用 sed 将字符串的一部分替换为 sed。 美元符号表示字符串的末尾。总脚本将是

OUTDIR=/home/sub_directory_2/level_2
for file in /home/sub_directory1/samples/SSTC/*_novoalign.bam; do
   echo Debug: Inputfile including path: ${file}
   OUTPUTFILE=$(basename $file | sed -e 's/_novoalign.bam$/_out.txt/')
   echo Debug: Outputfile without path: ${OUTPUTFILE}
   samtools depth -r chr9:218026635-21994999 < ${file} > ${OUTDIR}/${OUTPUTFILE}
done

注1: 你可以使用 file=${fullfile##*/} 这样的参数扩展来获取不带路径的文件名,但是你会在一小时内忘记语法。 比较容易记住的是basename和dirname,但是你还是要做一些处理。

注2: 当您的脚本第一次将目录更改为 /home/sub_directory_2/level_2 时,您可以跳过 basename 调用。
当dir中的所有文件都要处理时,可以使用星号。
当所有文件最多有一个下划线时,可以使用 cut。 您可能想要添加一些错误处理。当您想要输出文件中来自 samtools 的 STDERR 时,添加 2>&1.
这些会将您的脚本变成

   OUTDIR=/home/sub_directory_2/level_2
   cd /home/sub_directory1/samples/SSTC
   for file in *; do
       echo Debug: Inputfile: ${file}
       OUTPUTFILE="$(basename $file | cut -d_ -f1)_out.txt"
       echo Debug: Outputfile: ${OUTPUTFILE}
       samtools depth -r chr9:218026635-21994999 < ${file} > ${OUTDIR}/${OUTPUTFILE} 2>&1
    done