I know I can use a wildcard to extract files with names of a specific format in bash using the asterisk, like so:

$ ls
a01     a02     a03     a04     a05     a06     a07     a08     a09     b01     b02     b03     b04     b05     b06     b07     b08     b09
$ ls a*
a01     a02     a03     a04     a05     a06     a07     a08     a09
$ ls b*
b01     b02     b03     b04     b05     b06     b07     b08     b09

But if I wanted to do something like move all the files starting with a to a directory called a and move all the files starting with b to a directory called b, how would I do that with one command?

Can you do something like this:

$ mv *0* */

But somehow reference the first asterisk in the move-to argument?

1 Answer 1


One command, one line:

for n in *;do [ -f "$n" ] && case "$n" in a*) mv "$n" a/;; b*) mv "$n" b/;; esac; done

Alternatively, you could derive the name of the directory from the filename, but I did not show that initially, estimating it to be a longer line. For example, the statement in the loop would be (first try):

d=$(echo "$n" | sed -e 's/^\(.\).*/\1/'); [ -f "$n" ] && mv "$n" $d/

would use the first letter of the given filename to obtain the directory name. Compare with

[ -f "$n" ] && case "$n" in a*) mv "$n" a/;; *b) mv "$n" b/;; esac

for the case-statement. Actually not much longer, but harder to type on the fly. Because bash is mentioned, one can use its substring syntax ${parameter:offset:length} to shorten that line:

d=${n:0:1}; [ -f "$n" ] && mv "$n" $d/


[ -f "$n" ] && mv "$n" ${n:0:1}/

(I recall this as a bash extension, and do not find it in POSIX).

Regarding the actual question about reusing wildcards: that apparently refers to brace expansion. Those are expanded before the point where you would need them. Quoting the documentation:

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces. To avoid conflicts with parameter expansion, the string ‘${’ is not considered eligible for brace expansion.

  • Wow, that's a lot more convoluted than I expected. So there isn't something like backreferences in regex? May 14, 2015 at 23:51
  • yes/no: not with wildcards, but only for the expanded names. The loop I showed hard-codes the names and looks long -- but translating the name would add about a third to the length of the line, so I stopped there. The example makes sure that the source is a file, which makes it a little longer. May 14, 2015 at 23:57
  • bash does have substitutions which would avoid sed -- I do most of my scripting for POSIX applications. May 15, 2015 at 0:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .