0
$ cat test.sh
#! /bin/bash

if [ -f /home/amnesia/Persistent/yubikey-manager-qt.AppImage ]; then
  ykman="/home/amnesia/Persistent/yubikey-manager-qt.AppImage ykman"
elif [ -f /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman ]; then
  ykman="/Applications/YubiKey\ Manager.app/Contents/MacOS/ykman"
else
  printf "$bold$red%s$normal\n" "Could not find YubiKey Manager binary"
  exit 1
fi

$ykman list

$ test.sh
./test.sh: line 12: /Applications/YubiKey\: No such file or directory

./test.sh: line 12: /Applications/YubiKey: No such file or directory

How can I fix above error?

Using following approach solves issue on macOS but breaks things on Tails because of ykman AppImage requirement.

$ cat test.sh
#! /bin/bash

if [ -f /home/amnesia/Persistent/yubikey-manager-qt.AppImage ]; then
  ykman="/home/amnesia/Persistent/yubikey-manager-qt.AppImage ykman"
elif [ -f /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman ]; then
  ykman="/Applications/YubiKey Manager.app/Contents/MacOS/ykman"
else
  printf "$bold$red%s$normal\n" "Could not find YubiKey Manager binary"
  exit 1
fi

"$ykman" list

$ test.sh
./test.sh: line 12: /home/amnesia/Persistent/yubikey-manager-qt.AppImage ykman: No such file or directory

./test.sh: line 12: /home/amnesia/Persistent/yubikey-manager-qt.AppImage ykman: No such file or directory

Thanks for helping out!

sunknudsen
  • 6,356
  • 3
  • 39
  • 76
  • 1
    Use a function instead of a variable. `ykman() { /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman "$@"; }` – Jetchisel Aug 27 '21 at 14:30
  • @Jetchisel Thanks for helping out! I would like to avoid using function as I am using conditions to determine path. if a, thenykman="/path/to/a", elif b, ykman="/path/to/b"… – sunknudsen Aug 27 '21 at 14:32
  • Removing the backslash should be enough (as long as you keep the quotes) – Aserre Aug 27 '21 at 14:33
  • @Aserre Without backslash, I get `./test.sh: line 4: /Applications/YubiKey: No such file or directory`. – sunknudsen Aug 27 '21 at 14:34
  • Or if badly needed, mask it with another backslash: ```ykman="/Applications/YubiKey\\ Manager.app/Contents/MacOS/ykman"``` and use: ```"${ykman}" list``` – koyaanisqatsi Aug 27 '21 at 14:34
  • @koyaanisqatsi With two backslashes, I get `./test.sh: line 4: /Applications/YubiKey\: No such file or directory`. – sunknudsen Aug 27 '21 at 14:35
  • My bad, I tested on `zsh`. Try removing the backslash + quoting the variable, like so : `ykman="/Applications/YubiKey Manager.app/Contents/MacOS/ykman" ; "$ykman" list` – Aserre Aug 27 '21 at 14:35
  • @sunknudsen, then do the test and assignment inside the function as well? – Jetchisel Aug 27 '21 at 14:36
  • @Aserre using quotes, I get `./test.sh: line 4: /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman: No such file or directory` yet running `ls /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman` works. – sunknudsen Aug 27 '21 at 14:36
  • 1
    you didn't remove the backslash in your sample – Aserre Aug 27 '21 at 14:36
  • @Aserre Removing backslash and using double quotes worked. Thanks! That said, is there a way to use backslash so one doesn’t have to use double quotes each time one references `ykman` variable? – sunknudsen Aug 27 '21 at 14:39
  • 1
    nope. Space is part of your `IFS` default value. If you don't quote the variable, `bash` will split on every space. Your only solution would be to overwrite the value of the `IFS` variable (this will have an impact on the rest of your script, so be sure of what you are doing if you chose to do so) – Aserre Aug 27 '21 at 14:41
  • @sunknudsen, if your bash new enough, you could do`"${ykman@Q}"` otherwise try `"${ykman// /\\ }"` – Jetchisel Aug 27 '21 at 14:41
  • Does this answer your question? [Shell variable with spaces , quoting for single command line option](https://stackoverflow.com/questions/1724032/shell-variable-with-spaces-quoting-for-single-command-line-option) – Aserre Aug 27 '21 at 14:43
  • Or use `printf` with the `-v` flag and `q` something like `printf -v ykman '%q' "/Applications/YubiKey Manager.app/Contents/MacOS/ykman"` – Jetchisel Aug 27 '21 at 14:44
  • @Aserre Indirectly I suppose… Why doesn’t `IFS` break things when running command in terminal (for example when running `ls /Applications/YubiKey\ Manager.app/Contents/MacOS/ykman`)? – sunknudsen Aug 27 '21 at 14:45
  • 1
    Still I'd recommend a function instead to skip those gotchas. – Jetchisel Aug 27 '21 at 14:46
  • 1
    Try typing `ls "/Applications/YubiKey Manager"` : you'll see the space is not split. Here, you need the quotes because you are evaluating your command 2 times : 1) where you assign the value to your variable 2) when you call your variable as a command. You need the double quotes every time your content will be evaluated. Regarding your question : the space doesn't split because it is escaped – Aserre Aug 27 '21 at 14:57
  • Have you tried `open -a Yubikey list`? – Hai Vu Aug 27 '21 at 15:16
  • @Aserre Thanks again for helping out… unfortunately, using `"$ykman"` doesn’t work on Linux. Please see improved question. – sunknudsen Aug 31 '21 at 15:01

1 Answers1

1

you should quote variable dereferences to avoid the spaces in the variable being interpreted as space separating multiple values.

ykman="Application/YubiKey Manager.app/Contents/test.sh"
#use quotes while running 
./"$ykman"
test script output
arp5
  • 169
  • 10