I have a directory as follows

-rw-r--r-- 1 ualaoip2 mcm1    1073233 Sep 30 12:40 database.260.4-0.tar.gz
-rw-r--r-- 1 ualaoip2 mcm1  502373963 Sep 30 12:40 database.260.4-1.tar.gz
-rw-r--r-- 1 ualaoip2 mcm1  880379753 Sep 30 12:40 database.260.4-2.tar.gz
drwxr-xr-x 2 ualaoip2 mcm1       4096 Sep 30 13:41 db0file
drwxr-xr-x 2 ualaoip2 mcm1       4096 Sep 30 13:41 db1file
drwxr-xr-x 2 ualaoip2 mcm1       4096 Sep 30 13:41 db2file

and I want to move the file database...0 into folder0 &c...

What's the best way of doing this? I tried various variants of

for i in $(ls fi*) do; mv $i ./folder$i

but they renamed things and overwrote lots of stuff I didn't want!

I tried using variants of

find . -maxdepth 1 -type d -printf '%f\n' | sort /* why is it not sorted?

but couldn't get rid of the . for the current directory.

I used mkdir db{0..7} to create the files - is this the best way?

I would appreciate a couple of words of explanation with the answer - not just a monkey see, monkey do! :-)

2 Answers 2


If you can depend on the filename format, there is your command:

for i in $(seq 0 2); do mv database*-"$i".tar.gz "db${i}file"/; done

There is the description. Your files appear to have stable format database*-NUMBER.tar.gz and the same number is in the directory name dbNUMBERfile. We can just generate numbers up to the highest (in this example 0..2 and run for cycle for these numbers. In case of database simple $i is sufficient as it's bordered with - and ., however db$ifile wouldn't work, as there is no $ifile variable defined. So we have to use curly brackets db${i}file, then the $i is properly resolved.

set -o nullglob

for name in database*-*[0-9].tar.gz; do

    [ ! -d "folder$num" ] && mkdir "folder$num"

    mv "$name" "folder$num"

This will iterate over all the filenames that matches the database*-*[0-9].tar.gz pattern.

The num variable will be the number at the end of the filename (the number may be more than one digit) and it's picked out from the filename by first removing everything from the name up to and including the last -, and then removing the dot and everything afterwards.

The destination folders are created if they don't already exist.

By setting the nullglob shell option for bash first, we are guaranteed not to enter the loop at all if the pattern does not match any filenames.

You may change the pattern to just database*.tar.gz if you wish. I used a slightly more complicated pattern to be sure that all the components of the name are present that are actually used by the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.