使用mv命令不会将*识别为通配符

JM8*_*M88 0 bash shell awk mv

我有这个脚本,而且我知道其中的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)

anu*_*ava 6

问题是引用。Glob 模式应该在引号之外,因此您需要:

"${i}_"*"_sites.txt"
Run Code Online (Sandbox Code Playgroud)


Kei*_*son 5

mv命令无法识别*通配符;外壳可以。

这个:

foo*.txt
Run Code Online (Sandbox Code Playgroud)

扩展为当前目录中所有文件的列表,其名称以foo和开头.txt。如果您foo*.txt作为参数传递mv,该mv命令将永远不会看到*; 它只会看到文件列表。

这意味着,如果您有文件foo1.txtfoo2.txt,则:

mv foo*.txt bar*.txt
Run Code Online (Sandbox Code Playgroud)

不会重新命名foo1.txt,以bar1.txtfoo2.txtbar2.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)