linux wildcard usage in cp and mv

The find command can be used quite concisely in simple cases where you want to perform operations on wildcard (or more complex) filename matches. The technique below can be committed to memory ... almost !

This works by letting the find command run another command on each filename it finds. You can dry-run this example using echo instead of/in front of mv .

If we wanted to move all files in the current directory with name beginning 'report', to another parallel directory called 'reports' :

find . -name "report*.*" -exec mv '{}' ../reports/ \;

The wildcard string must be in quotes, the {} marking the filename that was 'found' must be in quotes, and the final semicolon must be escaped - all due to Bash/shell treatment of those characters.

Look at the man page for find for more uses: https://linux.die.net/man/1/find


Let's talk about how wildcards work for a minute.

cp *.txt foo

doesn't actually invoke cp with an argument *.txt, if any files matching that glob exist. Instead, it runs something like this:

cp a.txt b.txt c.txt foo

Similarly, something like

mv *.txt *.old

...can't possibly know what to do, because when it's invoked, what it sees is:

mv a.txt b.txt c.txt *.old

or, worse, if you already have a file named z.old, it'll see:

mv a.txt b.txt c.txt z.old

Thus, you need to use different tools. Consider:

# REPLACES: mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
for f in /data/*/Sample_*/logs/*_Data_time.err; do
  mv "$f" "${f%_Data_time.err}_Data_time_orig.err"
done

# REPLACES: cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*.sh; do
  cp "$f" "${f%.sh}_orig.sh"
done

# REPLACES: sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*_orig.sh; do
  if [[ -e "$f" ]]; then
    # honor the script's shebang and let it choose an interpreter to use
    "$f"
  else
    # script is not executable, assume POSIX sh (not bash, ksh, etc)
    sh "$f"
  fi
done

This uses a parameter expansion to strip off the tail end of the old name before adding the new name.

Tags:

Linux

Shell

Mv

Cp