How do I copy the latest file from one directory to another?

Run this:

cp -p "`ls -dtr1 /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/* | tail -1`" /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Backup1/

Here we have added -d option os ls to get the absolute path.

In your command, as ls is not returning absolute paths, you must run that from the source directory to get the file copied. As you have run it from some other directory that does not have the file, the error No such file or directory being shown.

Also as you have spaces in the path we need to quote ls -dtr1 /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/* | tail -1 so that shell does not do word splitting on the output of it.


It's because it depends from where you execute your cp. In your example, ls -tr1 /Users/Me/Whatever will return only website3.zip. If you run your cp from /tmp, then it will try to find the file /tmp/website3.zip.

To let ls display the full path, you should use the wildcard *. Depending on what you want, it may be useful to specify -d option to not let ls list the content of all sub-directories:

$ ls -tr1d /Users/Me/Whatever
...
website3.zip

$ ls -tr1d /Users/Me/Whatever/*
...
/Users/Me/Whatever/website3.zip

However, be careful in case the last modified entry is a directory. In this case, cp won't copy it if you omit the -R option.

If your files always have a .zip extension you may consider:

$ ls -tr1d /Users/Me/Whatever/*.zip

You may also get an error if your directory is empty. Why don't you script something like that:

#!/bin/bash

MY_DIR="/Users/Me/Documents/Coffi Work/FTP Backup Shell Script/Original/"
DEST="/Users/Me/Documents/Coffi Work/FTP Backup Shell Script/Backup1/"
FILEEXT="zip"

NEWEST=`ls -tr1d "${MY_DIR}/"*.${FILEEXT} 2>/dev/null | tail -1`

if [ -z "${NEWEST}" ] ; then
    echo "No file to copy"
    exit 1
elif [ -d "${NEWEST}" ] ; then
    echo "The most recent entry is a directory"
    exit 1
else
    echo "Copying ${NEWEST}"
    cp -p "${NEWEST}" "${DEST}"
fi

As others have already noticed, there are two problems with your approach. They have nothing to do with .zip vs .sh files, but with the names and locations of the files.

You need to put double quotes around command substitution. Otherwise they break at space characters. See Why does my shell script choke on whitespace or other special characters? for more details.

Furthermore the ls command outputs just the base name of the file, without the directory part. cp therefore only sees the base name and has no idea that you meant files in a different directory. One way to fix this is to switch to the desired directory first.

cd /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/
cp -p "`ls -tr | tail -1`" ../Backup1/ 

If you want just the latest zip file and not the latest file whatever it is:

cd /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/
cp -p "`ls -dtr *.zip | tail -1`" ../Backup1/ 

This will fail with a strange error message if the directory is empty or if there is a file name containing newlines or characters that are not printable in the current locale but these are relatively rare circumstances.

The option -d is a bit of additional safety in case there is a subdirectory whose name matches *.zip. You don't need the option -1, its effect is automatic when the output of ls is redirected to another command.

Alternatively, you can use zsh which makes this nice and easy thanks to its glob qualifiers.

cp -p /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/*(om[1]) /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Backup1/