Home > OS >  Script gives "if: command not found"
Script gives "if: command not found"

Time:01-14

I have a script like this:

HI="if [[ $(ioreg -r -k AppleClamshellState | grep '"AppleClamshellState"' | cut -f2 -d"=") = ' Yes' ]]; then ./lockscreen; fi"
while true; do $HI; sleep 1; done

Running bash ./test gives if: command not found. Replacing the outer double quotes with single quotes and the inner single quotes with '\'' also has the same problem.

Setting HI to echo Hello or rm -rf *.mp4 works fine.

Setting HI='if [ "" = "" ]; then echo Hi; fi' similarly fails.

It seems that because of the quotes, it assumes if is the command name, and everything else after it is an argument. I need a way to expand it out.

The point of this is that I want to make a function Loop that takes a string as an argument, and will execute that string every 10 seconds.

CodePudding user response:

Creating the loop function is straightforward. Calling it is the tricky part.

Here "$@" is the expansion of the arguments passed to loop. It's the same as writing "$1" "$2" "$3" ... for however many arguments there actually are:

loop() {
    while true; do
        "$@"
        sleep 10
    done
}

As you've experienced, variable expansion like this works fine for regular commands, but doesn't handle more complicated cases like if statements, | pipelines, && and || operators, or multi-line commands separated with ; and/or &.

The best way to support all of those features is for the caller to define a function and pass the function name to loop. Functions can use all of these features, and have the advantage of not requiring any complicated quoting or escaping:

hi() {
    if [[ $(ioreg -r -k AppleClamshellState | grep '"AppleClamshellState"' | cut -f2 -d"=") = ' Yes' ]]; then
        ./lockscreen
    fi
}

loop hi

Further reading:

CodePudding user response:

I can solve this by using do eval $HI. Of course, the problem is that if I use double quotes, then expansions are done at the first run, and if I use single quotes, it is expanded after its second run. I don't want it to be expanded, but evaluated at every run.

EDIT: I got around this by using \$, or even better, using single quotes (this did mean I had to escape all the single quotes though.

  •  Tags:  
  • Related