-1

[ -f *.zip ] is a working solution to check for the existence of one1 zip file, but [[ -f *.zip ]] isn't:

$ bash --version
[...]
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
[...]

$ ls -a
.    ..

$ touch a.zip

$ [ -f *.zip ] && echo true || echo false
true

$ [[ -f *.zip ]] && echo true || echo false
false

Why would [[ implementation not expand globs? Has it been documented to be an improvement on what [ did naturally (as it is a command invoked after glob has been expanded)?


1) Globs are not only useful to list multiple files, it is a valid solution to identify a unique file you only know part of the name.

YSC
  • 38,212
  • 9
  • 96
  • 149
  • I don't think it's unhelpful. In fact I found it very enlightening. Did you try it with multiple zips in your directory and see that it errors? Was that expected? I would agree with you with the follow up thyough... why doesn't the second one error? Why does it return `false` instead? To that I would suggest `touch "*.zip"` and rerun your second. One expands and the other doesn't. – JNevill Mar 01 '22 at 14:53
  • 1
    [_"Word splitting and filename expansion are not performed on the words between the `[[` and `]]`"_](https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html#index-_005b_005b), unlike for the `[` command. It's looking for a file _literally named `*.zip`_. Canonical: https://stackoverflow.com/questions/669452/are-double-square-brackets-preferable-over-single-square-brackets-in-b. – jonrsharpe Mar 01 '22 at 14:56
  • ...except for with == and !=. – DevSolar Mar 01 '22 at 14:57
  • One can also find the *"Word splitting and pathname expansion are not performed on the words between the [[ and ]];"* verbiage in the bash manpage `man bash` under the `Compound Commands` section. – JNevill Mar 01 '22 at 15:01
  • @JNevill This question ask not about the feature, but about its rationale. – YSC Mar 01 '22 at 15:06
  • Question has been rephrased. We might not understand "rationale" the same way, my bad I suppose. – YSC Mar 01 '22 at 15:10
  • My understanding of `bash\[[` compound command is that it was built to be less error prone than `test\[`. I would say that removing expansion seems to fit that bill. What would `-f` even mean if multiple files are returned post-expansion? I could see a usefulness for a test/flag for "One or more files fitting this pattern" might be useful but that would be an extra feature that `-f` doesn't fulfill with either `test` or `bash`. – JNevill Mar 01 '22 at 15:10
  • I typically use a `for` loop to check for a single file. `for f in *.zip; do [ -f "$f" ] || break; ...; done`. Either `$f` matches a file, or it doesn't. When it doesn't, you exit the loop before treating `$f` as a valid file name. – chepner Mar 01 '22 at 15:27
  • Your usage treats a failed test as a false result. – chepner Mar 01 '22 at 15:28

1 Answers1

1

What's the rationale behind [[ -f *.zip ]] not doing what a user might initially think?

The rationale is that [[ is not [ command, it is a different command with specific parsing rules, designed speed up execution and also to protect against mistakes related to globbing/filename expansion and quoting/word splitting, just like [ -f *.zip ].

what does it do exactly?

It checks if a file named *.zip literally with * exists.

$ touch '*.zip'
$ [[ -f *.zip ]] && echo true || echo false
true

[ -f *.zip ] will not work for checking if there are any files with .zip extension - it will error if there are more than two files matching the glob.

$ touch a.zip b.zip
$ [ -f *.zip ]
bash: [: a.zip: binary operator expected

See Test whether a glob has any matches in Bash for a way.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • We might understand "rationale" differently. I was hoping to find a (documented) justification for the decision `[[` took not to expand globs. Do you know of any? – YSC Mar 01 '22 at 15:05
  • Question updated – YSC Mar 01 '22 at 15:10
  • `Do you know of any?` `[[` does not require quotes. The justification is to speed up execution and protect against mistakes related to word splitting and globbing (just like the code you posted, `[ -f *.zip ]` has a bug). `[[` is with us from bash2.0, looking at CHANGES, I think you would have to ask Chet Ramey, but I think he will tell you the same. – KamilCuk Mar 01 '22 at 15:20
  • 1
    `[[ is actually not a command at all, unlike [, it's a keyword` Och nitpicky, it is a keyword _grammatically_, but in Bash documentation all over it is a "compound command" - a command. :p – KamilCuk Mar 01 '22 at 15:25
  • That's the thing, I'm actually hunting for a documented reason why glob expansion is not done. What was the developer decision based on? Opinions are interesting, and I agree with you, but that's not what I'm looking for. – YSC Mar 01 '22 at 15:41