2

I have a little shell script and cannot seem to figure out how to create a simple conditional statement.

big_width=$(($width > 1700))
big_height=$(($height > 1700))

if [ $extension != "jpg" || $big_width || $big_height ]; then

Gives the errors

[: missing ]
0: not found

Also IDK if this will give me what I want. The coniditional should be executed if $extension != "jpg or if one of the width/height variables are bigger than 1700.

Edit

Trying this code if [[ $extension != "jpg" ]] || ((width > 1700)) || ((height > 1700)); then gives a height: not found error. Any idea why the bash syntax is erroring out?

Edit

When I add this to my script

echo $0
echo $SHELL

It prints

source/images/shrink_img.sh
/bin/bash

So bash should be working right? I have no idea why this conditional syntax breaks things. I have tried changing file extensions from .sh to .bash and calling the script with bash instead of sh too.

James L.
  • 12,893
  • 4
  • 49
  • 60

3 Answers3

2

In C you can put a bare 0 or 1 where a boolean expression is expected. Not so in shell scripts. You also cannot use && and || inside of single square brackets. They need to be outside.

Option 1: Write all three tests explicitly.

if [[ $extension != "jpg" ]] || ((width > 1700)) || ((height > 1700)); then

Option 2: Use "boolean" variables.

((big_width  = width  > 1700))
((big_height = height > 1700))

if [[ $extension != "jpg" ]] || ((big_width)) || ((big_height)); then    

Option 3: Hide the tests behind functions.

big_width () { ((width  > 1700)); }
big_height() { ((height > 1700)); }

if [[ $extension != "jpg" ]] || big_width || big_height; then

(You'll notice that I switched to double square brackets. [[ ... ]] is more robust than [ ... ]. See this answer for an in depth explanation of the advantages of double brackets.)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Trying to use option 1 gives me `314: not found`, or whatever my `width` is. – James L. Oct 12 '17 at 00:33
  • I added `$` in front of width/height vars. If that isn't there then I receive `height: not found` issues. Other than that, it was a copy/paste. No idea why it's not working. Other methods aren't working either. – James L. Oct 12 '17 at 00:39
  • 1
    `$` is optional for variables referenced inside `((...))`. Are you for sure in bash? Do you have a `#!/bin/bash` shebang line at the top of your script? – John Kugelman Oct 12 '17 at 00:41
  • Yes, and I am calling it via `bash script.sh vars`. Not sure if that for sure means I am in bash though. – James L. Oct 12 '17 at 00:42
  • 3
    You can't use `||` inside `[...]`, but you can use it inside `[[ ... ]]` and `(( ... ))`. – chepner Oct 12 '17 at 01:09
  • Could you expand on that a bit @chepner? It looks like the `||` are outside of any brackets, what would be the correct way to write it? – James L. Oct 12 '17 at 15:08
  • `((width > 1700)) || ((height > 1700))` and `((width > 1700 || height > 1700))` both work. If you had multiple `[[ ... ]]` conditions you could likewise combine them. You can't do that with single `[ ... ]` though, only double brackets. – John Kugelman Oct 12 '17 at 15:17
  • Ah ok, I can see that you all were talking about the OP, and I was referring to the revisions made as suggested by John. We're all on the same page now. Any idea why using John's answer is erroring out for me? – James L. Oct 12 '17 at 16:05
  • @JamesLowrey It really sounds like you aren't actually running the script with `bash`. – chepner Oct 12 '17 at 16:31
  • I agree. Any ideas why that might be, given my shebang is correct and I am calling it via `bash script vars`? – James L. Oct 12 '17 at 16:36
  • I'll be honest, I've got no idea. You might want to open another question so you can show exactly what you're trying to run and what's happening. Make sure to create a [mcve]. – John Kugelman Oct 12 '17 at 17:19
1

The or operator is -o, and you need to use comparison -eq 0:

big_width=$(($width > 1700))
big_height=$(($height > 1700))

if [ $extension != "jpg"  -o  $big_width -eq 0  -o  $big_height -eq 0 ]; then
Jack
  • 5,801
  • 1
  • 15
  • 20
  • 3
    `-o` has been marked obsolescent, see [the POSIX spec](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html). See also [Tests and conditionals](http://mywiki.wooledge.org/BashGuide/TestsAndConditionals) in the Wooledge wiki, under "good practice". – Benjamin W. Oct 24 '17 at 13:48
1

If I understood the problem correctly, this piece of code will do the trick. You can also play around if you want to change the conditions.

    width=1701
    height=1699
    extension="jpg"

    if [ $extension != "jpg" ] || [ $width -gt 1700 ] || [ $height -gt 1700 ]; 
    then
        echo "Yay"
    else
        echo "Nay"
    fi
Guru
  • 148
  • 1
  • 12
  • This works for me, thanks. Any idea why John Kugleman's solution wasnt' working? – James L. Oct 24 '17 at 15:54
  • Some issues I see with John's suggestion. 1. "[" is a conditional statement - that is not used except for first condition. 2. Variables used lack "$". 3. ">" used instead of "-gt". Shell is also very sentimental about spaces especially for conditions but I see that John has been careful with that. – Guru Oct 25 '17 at 01:00
  • 1
    None of those are issues. Inside `((...))` variables don't need `$`, and `>` is the correct operator. When using bash it's better to use `[[` and `((` rather than `[` (single bracket). – John Kugelman Oct 25 '17 at 12:13
  • James, if this works and my answer doesn't, it really seems like your "bash" shell isn't actually bash because you're saying all my bash-isms don't work. `[` is an older sh-compatible syntax. You shouldn't have to fall back to it in proper bash. – John Kugelman Oct 25 '17 at 12:16
  • I agree John. I tried to add the bounty and changed the question title to try and figure out why the bash syntax isn't working. – James L. Oct 25 '17 at 14:32