Search code examples
bashmv

Can't use $myvar_.* to mv files starting with $myvar_


week=$(date +%W)

I'm trying to move files beginning with $week to another folder using mv.

So I have a file named:

25_myfile.zip

And the number at the beginning is a number of a week. So I want to move it using mv from the directory it's currently in to /mydir/week25/:

mv /mydir/$week\_.* /mydir/week$week;

But I get a stat error.


Solution

  • The problem

    When you say

    mv /mydir/$week\_.* /mydir/week$week;
    #                ^^
    

    You are using the syntax $var\_.* (or ${var}_.* if you don't want to have to escape the underscore) you are trying to use globbing, but failing because you use a regular expression syntax.

    The solution

    Use globbing as described in Bash Reference Manual → 3.5.8 Filename Expansion. That is

    After word splitting, unless the -f option has been set (see The Set Builtin), Bash scans each word for the characters ‘*’, ‘?’, and ‘[’. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of filenames matching the pattern (see Pattern Matching).

    mv /mydir/$week\_* /mydir/week$week;
    #                ^
    

    or, using ${ } to define the scope of the name of the variable:

    mv /mydir/${week}_* /mydir/week$week;
    #          ^    ^ ^
    

    Another approach

    You just need an expression like:

    for file in <matching condition>; do
         mv "$file" /another/dir
    done
    

    In this case:

    for file in ${week}_*; do
       mv "$file" /mydir/week"${week}"/
    done
    

    Because ${week}_* will expand to those filenames starting with $week plus _.

    See an example:

    $ touch 23_a
    $ touch 23_b
    $ touch 23_c
    $ touch 24_c
    $ d=23
    $ echo ${d}*
    23_a 23_b 23_c
    $ for f in ${d}*; do echo "$f --"; done
    23_a --
    23_b --
    23_c --