当程序在 cshell 中循环工作时,如何给出新的文件名?

当程序在 cshell 中循环工作时,如何给出新的文件名?

我有很多 .dat 文件,我想将它们转换为 .sac 文件(一种地震图文件)。我使用 xy2sac 程序转换文件(我没有编写代码),但我必须给转换后的文件一个我选择的新名称。

转换器代码的工作原理如下:

xy2sac filename.dat newfilename.sac

我想要做的是在 xy2sac 程序循环工作时给出我的新文件名。例如我的dat文件名是这样的:

BRGA_KO_disp_post_mij_conv0000_E.dat
BRGA_KO_disp_post_mij_conv0000_E.dat
BRGA_KO_disp_post_mij_conv0000_N.dat
BRGA_KO_disp_post_mij_conv0000_Z.dat
GADA_KO_disp_post_mij_conv0000_E.dat
GADA_KO_disp_post_mij_conv0000_N.dat
GADA_KO_disp_post_mij_conv0000_Z.dat
HYBL_KO_disp_post_mij_conv0000_E.dat
HYBL_KO_disp_post_mij_conv0000_N.dat
HYBL_KO_disp_post_mij_conv0000_Z.dat
ISK_KO_disp_post_mij_conv0000_E.dat
ISK_KO_disp_post_mij_conv0000_N.dat
ISK_KO_disp_post_mij_conv0000_Z.dat
TUZL_KO_disp_post_mij_conv0000_E.dat
TUZL_KO_disp_post_mij_conv0000_N.dat
TUZL_KO_disp_post_mij_conv0000_Z.dat

我想把他们的名字改成:

BRGA_KO__E.sac
BRGA_KO__E.sac
BRGA_KO__N.sac
BRGA_KO__Z.sac
GADA_KO__E.sac
GADA_KO__N.sac
GADA_KO__Z.sac
HYBL_KO__E.sac
HYBL_KO__N.sac
HYBL_KO__Z.sac
ISK_KO__E.sac
ISK_KO__N.sac
ISK_KO__Z.sac
TUZL_KO__E.sac
TUZL_KO__N.sac
TUZL_KO__Z.sac

所以我想选择 .dat 之前的前 8 个字符和最后一个字符。

我怎样才能做到这一点?

我使用了这个循环,但它不起作用,最终得到了 .dat 文件扩展名。

foreach file (`ls *.dat*`)
xy2sac *.dat *.sac << END
END
end

提前致谢。

答案1

如果您确实无法更改为更理智的 shell,那么在 中csh,您可以使用:s修饰符在变量内进行字符串替换

前任。

#!/bin/csh -f

foreach file ( *.dat )
echo xy2sac $file $file:s/disp_post_mij_conv0000//:s/.dat/.sac/
end

echo一旦您确信文件名正确,请删除

答案2

警告:我没有意识到您正在使用 csh,所以我的答案仅适用于 bash。如果这不是一个选择,其他答案提供了可用的解决方案。

您可以将=~运算符与BASH_REMATCH数组一起使用来匹配文件名的部分内容并将它们组合成新文件名:

#!/bin/bash
for file in *.dat
do
    if [[ $file =~ ([A-Z]+_[A-Z]+_).*(..)\.dat ]]
    then
        xy2sac $file ${BASH_REMATCH[1]}${BASH_REMATCH[2]}.dac
    fi
done

顺便说一句,您应该确保您的要求和示例匹配,这样我们就不必猜测您的实际含义,目前还不清楚您是否确实需要将空的此处文档输入到命令中。我已经构建了代码来匹配您的示例,但显然要匹配的第一个部分并不总是 8 个字符,并且您的意思是 .dat 之前的最后两个字符(包括_,)而不仅仅是最后一个。

答案3

一个建议:使用awk轻松剪切“_”和“.”并轻松访问您想要构建新文件名的部分

如果你是当然所有 *.dat 文件都具有您提到的确切结构(即,其中没有空格,始终有 6 个“_”,只有 1 个“.”等):

# solution with awk, which can easily define fields using a regex
# (here: "[_.]" so that either 1 "_" or 1 "." separates one field from the next)
# awk will check we presented a filename with the correct number of fields, and also

cd /correct/directory || exit 1   # ie, go to the right directory containing your .dat files, or exit
find ./ -name '*.dat' -print \
  | awk -F'[_.]' -v nbfield=8 '
       ( NF != nbfield ) {
           print "Error: file " $0 " ignored: does not have the right structure." ; 
           next;
       }
       ( NF == nbfield ) { 
           print "converting file: " $0 " ..."
           system("echo _remove_echo_when_ok_ xy2sac  " $0 "  " $1"_"$2"__"$(NF-1)".sac && echo OK || echo ___ko___ ") 
       }
     '

当然,当您认为它正常工作时:将"echo _remove_echo_when_ok_ xy2sac "(仅显示但不执行 xy2sac)替换为"xy2sac "(将执行它)

相关内容