The use case I can think of for -nt, would be updating a file if it is too old, or if it does not exist. Bash handles this just fine:

$ bash -c 'touch 2.txt; sleep 1; touch 1.txt; [ 1.txt -nt 2.txt ]; echo $?;
[ 1.txt -nt 3.txt ]; echo $?'

However Dash only works as expected if both files exist:

$ dash -c 'touch 2.txt; sleep 1; touch 1.txt; [ 1.txt -nt 2.txt ]; echo $?;
[ 1.txt -nt 3.txt ]; echo $?'

I am trying to understand the logic of the Dash code. You can work around this behavior like this:

$ dash -c 'touch 1.txt; [ ! -f 3.txt ] || [ 1.txt -nt 3.txt ]; echo $?'

but why should that be needed? Why did Dash choose this logic? Does it make sense to have the Dash logic in certain cases?

  • 2
    IIRC, in SQL, comparisons where the other operand is NULL, are always false. And in some languages, comparison against something that doesn't exist would thrown an error or an exception... – ilkkachu May 12 '18 at 18:34

Your question is rather opinionated, however in my opinion dash's logic makes more sense. If you want to compare if a file is newer than another, both files existing should be a requirement. This is clearly not the case as indicated in the bash manual though.

6.4 Bash Conditional Expressions

file1 -nt file2

True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.

Dash man page

file1 -nt file2

True if file1 and file2 exist and file1 is newer than file2.

why should that be needed?

Why should both files need to exist? A better question is why not? Why would you want to compare if file1 is newer than a non existent file? It's just a convoluted way to test if file1 exists. If you are really trying to compare if one file is newer than another, it's probably an issue that should cause an error if one of those files is missing.

Would it make sense with other comparison operators?

Comparing a file to a non existent file is sort of like comparing an integer to a null value. Would it make sense if [[ 1 -gt "" ]] evaluated to true? Well bash thinks that makes sense too...

$ bash -c '[[ 1 -gt "" ]] && echo yes'
$ dash -c '[ 1 -gt "" ] && echo yes'
dash: 1: [: Illegal number:
$ sh -c '[ 1 -gt "" ] && echo yes'
sh: line 0: [: : integer expression expected
  • ok - i think i see your point - you could say bash behavior is lazy and should not be allowed - to compare - Ruby File.mtime even raises an exception if the file does not exist – Steven Penny May 12 '18 at 17:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.