我有这个脚本,而且我知道其中的awk命令有效,但是当我想使用与该文件相同的名称保存输出时,它使用mv命令来执行任务,该命令*不用作通配符,而是用作通配符字符,最后得到一个名称如下的文件:
阿尔及利亚_BER _ * _ sites.txt
剧本:
#!/bin/bash
for i in Algeria_BER
do
echo awk 'FNR==NR{a[++i]=$0;next} {print a[FNR] RS $0}' \
reduced_filt_MAF_b37_chr1_${i}_ldhat.txt_names ${i}_*_sites.txt > $$.tmp &&
mv $$.tmp "${i}_*_sites.txt"
done
Run Code Online (Sandbox Code Playgroud)
该mv命令无法识别*通配符;外壳可以。
这个:
foo*.txt
Run Code Online (Sandbox Code Playgroud)
扩展为当前目录中所有文件的列表,其名称以foo和开头.txt。如果您foo*.txt作为参数传递mv,该mv命令将永远不会看到*; 它只会看到文件列表。
这意味着,如果您有文件foo1.txt和foo2.txt,则:
mv foo*.txt bar*.txt
Run Code Online (Sandbox Code Playgroud)
会不会重新命名foo1.txt,以bar1.txt和foo2.txt对bar2.txt-因为bar*.txt只能扩展到文件列表已经存在。如果没有与之匹配的现有文件bar*.txt,则以上内容将扩展为:
mv foo1.txt foo2.txt bar42.txt
Run Code Online (Sandbox Code Playgroud)
除非bar42.txt碰巧是目录,否则这是一个错误。它将根据当前恰巧存在的文件以其他各种方式进行扩展-而且可能都不是您想要的文件。
如果没有与给定通配符匹配的文件,则行为取决于外壳程序和当前设置。在中bash,使用默认设置时,通配符只是不展开-这可能就是为什么您要获得名称为的文件的原因*。
有大量的重命名工具可以满足您的需求(我自己还没有使用过)。
我经常使用的另一种方法是将文件列出为文本文件,手动编辑文件,然后将其作为脚本运行。例如,我可以这样做:
ls foo*.txt > tmp
Run Code Online (Sandbox Code Playgroud)
然后手动编辑tmp以将每一行变成执行我想要的命令:
foo1.txt
foo2.txt
Run Code Online (Sandbox Code Playgroud)
->
mv foo1.txt bar1.txt
mv foo2.txt bar2.txt
Run Code Online (Sandbox Code Playgroud)
然后运行命令:
. ./tmp
Run Code Online (Sandbox Code Playgroud)