Copy a file and append a timestamp

66,735

One of your problems is that you left out the double quotes around the command substitution, so the output from the date command was split at spaces. See Why does my shell script choke on whitespace or other special characters? This is a valid command:

cp -a /home/bpacheco/Test1 "/home/bpacheco/Test2-$(date +"%m-%d-%y-%r")"

If you want to append to the original file name, you need to have that in a variable.

source=/home/bpacheco/Test1
cp -a -- "$source" "$source-$(date +"%m-%d-%y-%r")"

If you're using bash, you can use brace expansion instead.

cp -a /home/bpacheco/Test1{,"-$(date +"%m-%d-%y-%r")"}

If you want to copy the file to a different directory, and append the timestamp to the original file name, you can do it this way — ${source##*/} expands to the value of source without the part up to the last / (it removes the longest prefix matching the pattern */):

source=/home/bpacheco/Test1
cp -a -- "$source" "/destination/directory/${source##*/}-$(date +"%m-%d-%y-%r")"

If Test1 is a directory, it's copied recursively, and the files inside the directory keep their name: only the toplevel directory gets a timestamp appended (e.g. Test1/foo is copied to Test1-05-10-15-07:19:42 PM). If you want to append a timestamp to all the file names, that's a different problem.

Your choice of timestamp format is a bad idea: it's hard to read for humans and hard to sort. You should use a format that's easier to read and that can be sorted easily, i.e. with parts in decreasing order of importance: year, month, day, hour, minute, second, and with a separation between the date part and the time part.

cp -a /home/bpacheco/Test1 "/home/bpacheco/Test2-$(date +"%Y%m%d-%H%M%S")"
cp -a /home/bpacheco/Test1 "/home/bpacheco/Test2-$(date +"%Y-%m-%dT%H%M%S%:z")"
Share:
66,735

Related videos on Youtube

Brian
Author by

Brian

Updated on September 18, 2022

Comments

  • Brian
    Brian almost 2 years

    I've got two issues with my script that copies files and adds a timestamp to the name.

    cp -ra /home/bpacheco/Test1 /home/bpacheco/Test2-$(date +"%m-%d-%y-%T")
    

    The above adds Test2 as the filename, but I want it to keep the original source file's file name which in this example is named Test.

    cp -ra /home/bpacheco/Test1 /home/bpacheco/Test2-$(date +"%m-%d-%y-%r")
    

    The other issue is when I add the %r as the timestamp code I get the error stating that target "PM" is not a directory. I'm trying to get the timestamp as 12-hour clock time.

    • Admin
      Admin about 9 years
      Adding AM/PM add extra space in the filename. If you insist to have it try something like: cp -ra /home/bpacheco/Test1 "/home/bpacheco/Test2-$(date +%m-%d-%y-%r)"
    • Admin
      Admin over 3 years
      For a classic Y-m-d_H-i-s + timezones: "newfile_$(date '+%Y-%m-%d_%H-%M-%S%z(%Z)')"
  • Atul Vekariya
    Atul Vekariya about 9 years
    Gilles, the first command will not work IMHO, check the positions of double quotes. And see my comment to the question
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 9 years
    @RomeoNinov What's wrong with the first command? Did you run it and get an error?
  • Atul Vekariya
    Atul Vekariya about 9 years
    You are right, date command is executed in subshell
  • Brian
    Brian about 9 years
    Gilles, using your above example, how would I copy the file with the above mentioned timestamp information to another directory. The following command does not work: cp -a /home/bpacheco/Test1/Test{,"-$(date +"%m-%d-%y-%r")"} /home/bpacheco/Test2
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 9 years
    @Brian I'm not sure I've understood your comment, but see my edit.
  • Brian
    Brian about 9 years
    Gilles, what I mean is when I use your command cp -a /home/bpacheco/Test1{,"-$(date +"%m-%d-%y-%r")"} it only copies the file within the source directory. Where in that command do I specify the destination directory?
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 9 years
    @Brian That command with the braces is a shortcut for cp -a /home/bpacheco/Test1 /home/bpacheco/Test1"-$(date +"%m-%d-%y-%r")". If your command doesn't have this form, because you want the destination not to start with /home/bpacheco/Test1, then you can't use braces, you need to spell it out, like in my other examples.
  • Dandelion
    Dandelion about 6 years
    For SOURCE variable I needed to use uppercase letters to get it working!
  • Vicky Dev
    Vicky Dev over 3 years
    @Gilles'SO-stopbeingevil' How can I achieve this when,the file path is a command line argument like $1 or $2 and I don't wanna mess up the file extension ?
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 3 years
    @VickyDev I don't know exactly what you want, but try building on this: directory="${1%/*}"; base="${1##*/}"; extension=${base##*.}; base=${base%.*}. Note that this simple approach doesn't handle the case where $1 ends with a slash (designating a directory) or when it's a file name with no extension. In zsh, you can use $1:h, $1:t:r and $1:e which handle these cases correctly.