I have a folder contains one or more tar.gz files. I want to add current date before each files when the script run.

For example:

Two file name(those files will be created each day, but the name will remain the same):


In first day(2011-10-07), those two files will be renamed to:


In next day(2011-10-08), they are changed to:


Finally, the folder contains the following files:


How to achieve this using one line? I tried to use "rename" command, but I can only add the date after the file, not before.

My code

cdate=`date +"%Y-%m-%d"`; rename .gz .gz.$cdate *.gz

Clearly, the key is to avoid renaming files that already have a date prefix.

cdate=$(date +"%Y-%m-%d")
shopt -s extglob
for file in !([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*.gz); do
  mv "$file" "${cdate}_$file"
  • Thank you. I modified a little because I have some other files in same folder and it works perfect now. cdate=$(date +"%Y-%m-%d") shopt -s extglob for file in [a-z 0-9]*.gz ; do mv "$file" "${cdate}_$file" done – garconcn Oct 7 '11 at 18:50
  • 1
    I'd recommend using for file in file*.gz instead of that "messy" regex. – frogstarr78 Oct 7 '11 at 19:27

Your example code might get you things like file1.2011-10-07.2011-10-08.tar.gz and I doubt that's what you want.

In addition, rename is not a standard command so it really depends on what yours does.

Since you say there are only ever a fixed number of files with fixed names, you could probably use a simple script like:

cdate=$(date +%Y-%m-%d)
for file in file1.tar.gz file2.tar.gz; do
    mv "$file" "$cdate"_"$file"
  • Thank you. The file name are fixed, but later, there maybe more files in the same folder. – garconcn Oct 7 '11 at 18:53

Assuming the files will never contain underscores in their names, a simple bash 4+ solution would be to use extglob:

shopt -s extglob
today=$(date +%F)
for f in ./!(*_*).tar.gz; do mv "$f" "$today"_"$f"; done

A more robust version:

shopt -s extglob
today=$(date +%F)
for f in ./!(????-??-??_*).tar.gz; do mv "$f" "$today"_"$f"; done

You can do it without resorting on bashisms (loops and/or extglob mode) and just use find, cut, grep and xargs.

find . -maxdepth 1 -type f | \
    cut -c3- | \
    grep -v '^\.' | \
    grep -v '^[0-9][0-9][0-9][0-9]\-[0-9][0-9]-[0-9][0-9]_' | \
    xargs -n 1 -I {} echo mv "{}" "`date +"%Y-%m-%d"`_{}"

Remove the echo to apply the changes instead of just printing the mv commands.

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.