1

I am making a bash script to run in a directory with files generated everyday and copy the most recent file to another directory.

I am using this now

for [FILE in directory]
do
  if [ls -Art | tail -n 1]
    something...
  else
    something...
  fi
done

I know this is not alright. I would like to compare the date modified of the files with the current date and if it was equal, copy that file then.

How would that work or is there an easier method to do it?

1
  • Instead of using ls, look into find with option -mtime. It will list files that are older than ? day(s). You can then use the -exec option to do something simple, or loop on the files (see FAQ001) if it is more complex (mywiki.wooledge.org/BashFAQ/001). Commented Oct 25, 2021 at 23:32

2 Answers 2

1

We could use find:

find . -maxdepth 1 -daystart -type f -mtime -1 -exec cp -f {} dest \;

Explanation:

  • -maxdepth 1 limits the search to the current directory.
  • -daystart sets the reference time of -mtime to the beginning of today.
  • -type f limits the search to files.
  • -mtime -1 limits the search to files that have been modified less than 1 day from reference time.
  • -exec cp -f {} dest \; copies the found files to directory dest.

Note that -daystart -mtime -1 means anytime after today 00:00 (included), but also tomorrow or any time in the future. So if you have files with last modification time in year 2042 they will be copied too. Use -mtime 0 if you prefer coping files that have been modified between today at 00:00 (excluded) and tomorrow at 00:00 (included).

Note also that all this could be impacted by irregularities like daylight saving time or leap seconds (not tested).

Sign up to request clarification or add additional context in comments.

Comments

1

The newest file is different from file(s) modified today.

Using ls is actually a pretty simple and portable approach. The stdout output format is defined by POSIX (if not printing to a terminal), and ls -A is also in newer POSIX standards.

It should look more like this though:

newest=$(ls -At | head -n 1)

You could add -1, but it AFAIK it shouldn’t be required, as it’s not printing to a terminal.

If you don’t want to use ls, you can use this on linux:

find . -mindepth 1 -maxdepth 1 -type f -exec stat -c ‘%Y:%n’ {} + |
sort -n |
tail -n 1 |
cut -d : -f 2-

Note using 2- not 2 with cut, in case a filename contains :.

Also, the resulting file name will be a relative path (./file), or an empty string if no files exist.

2 Comments

Processing ls output is discouraged for very good reasons. In this case one of these reasons is that file names can contain newline characters. Note that the same issue holds with your find-based solution: it will fail if a file name contains newline characters. Note also that {} is missing in your find command.
@RenaudPacalet Yeah I left out {}, fixed. The newline issue is ever present if parsing a file list, regardless of it’s produced by ls or not. It can be addressed by using -print0 with find, and adding -z to the other utilities, if on GNU.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.