10

I was writing an if statement which checked if a file is readable and exists by doing the following:

if [[ -r "$upFN" && -f "$upFN" ]]; then
....
fi

Then I thought, surly you can make this smaller, something maybe like this:

if [[ -r -f "$upFN" ]]; then
....
fi

But this doesn't work, it returns errors:

./ftp.sh: line 72: syntax error in conditional expression
./ftp.sh: line 72: syntax error near `"$upFN"'
./ftp.sh: line 72: `if [[ -r -f "$upFN" ]]; then'
Mint
  • 14,388
  • 30
  • 76
  • 108

2 Answers2

13

AFAICT, there is no way to combine them further. As a portability note, [[ expr ]] is less portable than [ expr ] or test expr. The C-style && and || are only included in bash so you might want to consider using the POSIX syntax of -a for and and -o for or. Personally, I prefer using test expr since it is very explicit. Many shells (bash included) include a builtin for it so you do not have to worry about process creation overhead.

In any case, I would rewrite your test as:

if test -r "$upFN" -a -f "$upFN"
then
  ...
fi

That syntax will work in traditional Bourne shell, Korn shell, and Bash. You can use the [ syntax portably just as well.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113
  • I always thought that [[ expr ]] was safer then [ expr ] when using variables in them. I wasn't aware that || and && only work in bash, will use -a -o as you suggested from now on. Cheers – Mint Jan 11 '11 at 03:54
  • 3
    So when should Bash-specific features be used? – Dennis Williamson Jan 11 '11 at 11:58
4

Is there ever a case where a file would be readable but it doesn't exist? Don't bother checking for existence when readability will tell you all you need.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • 3
    `-r` checks for readability and `-f` checks for a *file* that exists. The `-r` portion could succeed for a directory and the `-f` will fail. The post didn't mention that `-f` requires the item to be a file. `-e` checks for existence. – D.Shawley Jan 11 '11 at 03:19
  • I thought that -f and -r will never succeeded if the file doesn't exist, never heard of the -e, will have to check the man. – Mint Jan 11 '11 at 03:28
  • 1
    I just realized, that there is a case where `-r ` is true and `-f && -r ` is not: for a readable directory. – Oliv Jun 01 '16 at 11:53
  • Yes, @Oliv. That's what D. Shawley pointed out — the distinction between `-f` and `-e`. I don't think it's an important distinction in this case because I think Mint believed `-f` to be acting like `-e` all along. That is, I think the original use of `-f` was a mistake. – Rob Kennedy Jun 01 '16 at 12:03
  • I took it to mean that the file might exist, but you may not have read permissions. Ex.: `/var/log/secure`. – Erik Bennett Sep 09 '17 at 06:03