简体   繁体   中英

Check last modified date is within n seconds

I need to check the last modified date of all files within a directory to see if the latest file has been modified within some arbitrary period. Eg. 200 seconds.

Here's the twist, it also has to be a one-liner (its a Marathon health check and I can't rely on a file system being there for a script file).

Here's what I have so far:

ls -v | tail -n 1 | expr $(date +%s) - $(xargs date +%s -r) | if [ $PREV -gt 100 ]; then echo 1; else echo 0; fi

The ls -v sorts directory contents in "natural order" (the file names are monotonically increasing), so the latest file will be always be the last. tail -n 1 gets the last value.

Then expr $(date +%s) - $(xargs date +%s -r) subtracts the file's last modified date from now as a unix timestamp.

Next I want to pass the result forward to an if statement and return 0 or 1 depending on comparison with a constant. But I can't work out how to get the pipe output into the if statement.

Note: I'm aware I could have the if check in the previous pipe wrapping the subtraction, but I think that the one-liner is already confusing enough as it is.

Any help appreciated. Host OS is Linux. Bash shell.

Assuming GNU find (a fair assumption, given other GNU tools used in the question):

if [[ $(find . -maxdepth 1 -type f -newermt '-200 seconds' -print -quit) ]]; then
  echo "The newest file is less than 200 seconds old"
else
  echo "The newest file is more than 200 seconds old"
fi

On a system with BSD tools (such as MacOS), this might instead be:

if [[ $(find . -maxdepth 1 -type f -mtime -200s -print -quit) ]]; then
  echo "The newest file is less than 200 seconds old"
else
  echo "The newest file is more than 200 seconds old"
fi

Either of the above (as appropriate for the current platform) will have find scan the directory until they find a single file less than 200 seconds old; and will stop at that point and print the name of that file. This makes the search considerably more efficient for large directories than having ls sort the entire list (or to continue to scan for more files after one has already been found).

Note also the use of [[ ]] , which suppresses string-splitting -- with [ ] , quotes around $( ) would be needed to ensure correct behavior with filenames having spaces in their names, or files whose names could be expanded as glob expressions.

This code works.

if [ `expr $(date +%s) - $(stat -c %Y $(ls -t | head -n 1))` -gt 100 ];then echo 1;else echo 0;fi

How does it work?

ls -t - lists the files based on the time.

head -n 1 - gives first latest file.

date +%s gives time elapsed since epoch.

stat -c %Y - gives modification time since epoch

expr - subtracting present date from modified file date.

EDIT - 1

As per Charles advice

echo $(( $(date +%s) - $(printf '%s\\0' * | xargs -0 stat -c '%Y' | sort -g | tail -n 1) > 100 ))

This is more elegant way of doing.

I don't think I understand what you are looking for but you may try below

PREV=$(ls -v | tail -n 1 | expr $(date +%s) - $(xargs date +%s -r)) ; if [ $PREV -gt 100 ]; then echo 1; else echo 0; fi

If you're looking for something else then please give few more hints. And what's $PREV here? You're comparing this with 100 inside if but where does PREV value come from?

Answering my own question, I came up with:

ls -v | tail -n 1 | expr $(date +%s) - $(xargs date +%s -r) | if [ $(xargs) -gt 150 ]; then echo 1; else echo 0; fi

The modification I needed was using command substitution: $(xargs) to get the previous pipe output.

But I like the answer from bigbounty better than my solution as its cleaner. Marking as solved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM