check if file does not exist or is older than another in csh

j-hap picture j-hap · Jan 6, 2016 · Viewed 7.9k times · Source

in C-shell I need to check if a file exists or if it is older than another file (or in this example older than 5 seconds from the beginning of unix time). if the file does not exist or is old, some stuff should be executed.

In my example "bla.txt" does not exist, so the first condition is true

if ( ! -f bla.txt || `stat -c "%Y" bla.txt` > 5 ) echo 1
stat: cannot stat `bla.txt': No such file or directory
1

Problem is, if I combine these conditions in an if statement, the second one (age of file) is executed although the first one is already true and gives an error because the file is not there.

in bash, everything works as it should

if [ ! -f bla.txt ] || [ `stat -c "%Y" bla.txt` > 5 ]; then echo 1; fi
1

any ideas on how to achieve this behaviour in csh WITHOUT an else if? I don't want to have the commands to execute twice in my code.

thanks!

Answer

fork2execve picture fork2execve · Jan 6, 2016

CSH has a parser which, to be honest, doesn't deserve the name.

The issue in this particular instance is that it doesn't evaluate the left side of the || construct first before starting stat (as you've seen). As you're depending on the standard output of stat you can't redirect output via >& /dev/null either, and redirection of just stderr is a bit of a nuisance (see Redirecting stderr in csh).

If you want clean csh code that is still understandable but do not want to code the actual code call twice, I think the cleanest solution is to use an intermediate variable. Something like this:

#!/bin/csh
set f=$1
set do=0
if ( ! -f $f ) then
  set do=1
else
  if ( `stat -c "%Y" $f >& /dev/null ` < 5 ) set do=1
endif

if ( $do ) echo "File $f does not exist or is older than 5s after epoch"

(Note that your original code also had the age test reversed from your prose.)