5 ms·
Now do [ ... ] and [[ ... ]] I'm still not sure when to use one or the other. I use double brackets by default until something doesn't work.
by theandrewbailey 9mo ago
Now do [ ... ] and [[ ... ]]
I'm still not sure when to use one or the other. I use double brackets by default until something doesn't work.
- stabbles 9mo agoDouble brackets are less portable. For example musl linux does not come with bash by default, and your script fails. When unsure, use shellcheck.
- a3w 9mo ago[[ is built in, so "test[" as an /usr/bin artifact never exists? (What to call that proposed program, test2, or test[ ?)
- duskdozer 9mo agoYou mean shellcheck will detect when single brackets won't be enough? I've also just defaulted to double because I never really looked into it
- stabbles 9mo agoYeah, if you set the shebang `#!/bin/sh` (which is portable), shellcheck will complain about double brackets. It also helps you do quoting correctly when using single brackets.
- duskdozer 9mo agoI see. I've always just used `#!/usr/env/bin bash`. I wonder if there's a directive to hint at incompatibilities without changing it? I'll have to see. And this isn't meant snarkily - why should I care if my scripts are portable? I've worked on a number of different devices and types but have seemingly always had access to bash.
- PhilipRoman 9mo ago[[...]] is non-portable and has an extremely quirky corner case with variable expansion in arithmetic contexts, what's not to love?
- ndsipa_pomu 9mo agoI'm intrigued - any info on that? I personally use ((...)) for arithmetic tests and [[...]] for all other tests as I just target new versions of BASH and don't care much about POSIX compatibility.
- PhilipRoman 9mo agoThis is completely safe: [ "${payload}" -eq 42 ] This can evaluate arbitrary code: [[ "${payload}" -eq 42 ]] Here is one example of a malicious payload: payload='a[$(touch /tmp/pwned)]'
- ndsipa_pomu 9mo agoThanks. Now I need to figure out whether (( payload == 42 )) is safe.
- ndsipa_pomu 9mo agoIt appears not.
- account42 9mo agoIt also does wildcards though, with POSIX you'll need a case statement for that.
- nickjj 9mo ago[[ ... ]] supports regex comparisons and lets you combine multiple conditions in a single bracket group using && and || instead of remembering to use -a / -o. I usually default to [ ... ] unless I need features that double brackets provide.
- ndsipa_pomu 9mo agoUse ((...)) for arithmetic tests and [[...]] for other tests. [...] is for POSIX compatibility and not as useful as [[...]] though I don't remember the specifics.
- zzzeek 9mo agoyeah, if [ is a command in /bin/ what is [[ ?
- SAI_Peregrinus 9mo agoA builtin part of the shell, just like `if` and `then` and `fi`. Not all shells have `[[`, the one that doesn't which people unknowingly run into most is probably `dash` as used by Alpine Linux. POSIX doesn't require `[[` in a shell, BASH & Zsh support it but others often don't.
- zzzeek 9mo agoright so "[" is a file in /bin, "[[" is implicitly part of the shell, so that's as bad as I thought
- xp84 9mo agoIf shipping something that must run on sh, check your life choices and use [ - otherwise [[ is better. Honestly though I’ve been much happier since I stopped writing anything complex enough to have conditionals in Shell. Using a real scripting language like Ruby, Python, even PHP or Perl if you know them, is better. In the Ruby case I just use `%x( … )` when I need to run shell commands (there are some things shell does great like passing pipelines of text through 5 programs) and let the logic part be in Ruby.