Using mv command won't recognize * as wildcard

2019-09-19 12:45发布

问题:

I have this script, and I know the awk command in it works, but when I want to save the output using the same name of the file it used to do the task using the mv command the * is not used as a wildcard but instead as a character and I end up with a file with a name like this:

Algeria_BER_*_sites.txt

The script:

#!/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

回答1:

Problem is quoting. Glob pattern should be outside quote so you need:

"${i}_"*"_sites.txt"


回答2:

The mv command doesn't recognize the * wildcard; the shell does.

This:

foo*.txt

expands to a list of all files in the current directory whose names start with foo and end with .txt. If you pass foo*.txt as an argument to mv, the mv command never sees the *; it only sees the list of files.

Which means that if you have files foo1.txt and foo2.txt, this:

mv foo*.txt bar*.txt

will not rename foo1.txt to bar1.txt and foo2.txt to bar2.txt -- because bar*.txt can only expand to a list of files that already exist. If there are no existing files matching bar*.txt, then the above expands to:

mv foo1.txt foo2.txt bar42.txt

which is an error unless bar42.txt happens to be a directory. It will expand in various other ways depending on what files happen to exist at the moment -- and none of them are likely to be what you want.

If there are no file matching a given wildcard, the behavior depends on the shell and your current settings. In bash, with default settings, the wildcard just isn't expanded -- which is probably why you're getting a file with a * in its name.

There are bulk rename tools that will do what you want (I haven't used them myself).

Another approach I often use is to list the files to a text file, edit the file manually, and then run it as a script. For example, I might do this:

ls foo*.txt > tmp

then manually edit tmp to turn each line into a command that does what I want:

foo1.txt
foo2.txt

-->

mv foo1.txt bar1.txt
mv foo2.txt bar2.txt

and then run the command:

. ./tmp


标签: bash shell awk mv