0

I have a bash script that stores the output of a file comparison. The variable becomes something like: thing="/path/to/file - differ: byte 2, line 3".

In later lines I want to check that thing is not empty. However, when I try comparing them, it interprets thing as a command and not simply as a string.

My code is somewhat as follows:

#!/bin/bash

thing="/path/to/file - differ: byte 2, line 3"
if ["$thing" != ""]; then
    echo
    echo "Something went wrong"
else
    echo "Everything worked"
fi

Rather than saying thing is not an empty string, I get an error message that says something like

bash: [/path/to/thing - differs: byte2, line 3: No such file or directory.

How can I ensure that a comparison is happening between strings and that thing is not being interpreted as a command?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
mkamerath
  • 312
  • 2
  • 12
  • Try "${thing}". – Sudosu0 Oct 04 '19 at 00:04
  • The code with `if ["$thing" != ""]; then` is clearly incorrect — you need `if [ "$thing" != "" ]; then`, though you could also test `if [ -n "$thing" ]; then` (`-n` for not-empty). (There's also `-z` for 'is zero characters — empty'.) Don't post approximations — it gets people annoyed. Post actual code. **And use [https://www.shellcheck.net/](https://www.shellcheck.net/)** Spacing is critical in shell scripts — no spaces around assignments; spaces around arguments to commands. – Jonathan Leffler Oct 04 '19 at 00:04
  • `["$thing" != ""]` should be `[ "$thing" != "" ]`. Works for me this way. You could use `[ -z "$thing" ]` as well. – Pacifist Oct 04 '19 at 00:04

1 Answers1

3

Try this instead:

#!/bin/bash
thing="/path/to/file - differ: byte 2, line 3"
if [[ -n "$thing" ]]; then
    echo "Something went wrong"
else
    echo "Everything worked"
fi

Notice the double [[]] pairs. That will make use of Bash's internal test.

Use help test on Bash's command prompt to get more information.

EDIT: As explained by Jonathan in the comments, using any of [ … ] or [[ … ]] or test uses a built-in internal command in Bash. Section CONDITIONAL EXPRESSIONS of man bash (or Conditional Expressions, Conditional Constructs and Bourne Shell Built-ins) explains that. However, while [ … ] and test are logically the same (the only difference is that [ expects its last argument to be ] but test has no analogous expectation), the tests implemented by [[ … ]] are subject to different parsing rules from [ … ] and test, and [[ … ]] implements some extra test capabilities missing from the other.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
accdias
  • 5,160
  • 3
  • 19
  • 31
  • 2
    Using `[` and `]` also uses Bash's internal `test` (aka `[`) command — it's just different from the `[[` … `]]` testing command. – Jonathan Leffler Oct 04 '19 at 00:07
  • On most Linux distributions, ```[``` is a symlink for ```/usr/bin/test```. Does that still true in this case? – accdias Oct 04 '19 at 00:10
  • Yes, but `bash` doesn't run `/usr/bin/test` or `/usr/bin/[` when you type `[` — in fact, it is not unknown for there to be differences in behaviour between the internal (built-in) `test` and the external (built-out?) `test`. The `[` (aka `test`) command has been built into shells for a very long time — certainly since Unix SVR4 and I think considerably earlier. And SVR4 dates from the mid-80s or thereabouts. It wasn't built into the 7th Edition (Version 7) Bourne shell, though; then it was a separate standalone command. – Jonathan Leffler Oct 04 '19 at 00:12
  • Good to know. I prefer using the internals whenever possible to avoid calling out external programs. That gives me the (not proofed) sense of performance improvement. :-) – accdias Oct 04 '19 at 00:13
  • There absolutely is a difference between using `[[ ]]` and using `[ ]`/`test`: quoting, support for patterns and regular expressions... – Benjamin W. Oct 04 '19 at 03:21