5

I am using dash as /bin/sh. In my script, I have following line:

SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.*

Which is supposed to match file /tmp/ssh-abcdefghijkl/agent.1234. Even when the file exists, the script does not expand the pattern, and the variable instead contains the literal pattern:

echo $SSH_AUTH_SOCK
/tmp/ssh-????????????/agent.*

but when I do the same from commandline, it expands the pattern:

sh -c 'SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.* ; echo $SSH_AUTH_SOCK'
/tmp/ssh-abcdefghijkl/agent.1234

why does the pattern expansion (wildcard matching) not work in my script ?

1
  • Show the whole script. Or, a complete script that exhibits the problem, and also how you run the script.
    – ilkkachu
    Aug 5 at 7:38
12

Filename globbing does not happen in assignments like

SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.*

In your code where it appears to be working, you get your expected output because you do not quote the expansion of $SSH_AUTH_SOCK. What your sh -c script is doing is assigning the literal string /tmp/ssh-????????????/agent.* to SSH_AUTH_SOCK, and then the shell applies the globbing when you use that variable unquoted with echo.

The reason it doesn't behave the same way when you try it on the command line (echo $SSH_AUTH_SOCK prints the literal pattern) could be because you may be using the zsh shell (which does these things differently), or you have used set -f in the shell to turn off filename globbing, or there are simply no matching pathnames.

If you want to do something like what you are proposing, then use

set -- /tmp/ssh-????????????/agent.*
SSH_AUTH_SOCK=$1

This first sets the positional parameters to all pathnames that match the given pattern (in lexical order). It then assigns the first of these pathnames to the variable SSH_AUTH_SOCK.

If no pathnames match the pattern, the pattern will be left unexpanded and later assigned to the variable as it is.

In the bash shell, you could use a named array in place of the positional parameters:

names=( /tmp/ssh-????????????/agent.* )
SSH_AUTH_SOCK=${names[0]}
3
  • 2
    Bearing in mind that in sh or bash, if the glob doesn't match any file, the pattern is left unexpanded (in bash, the failglob or nullglob options can be used to avoid that. See also the N glob qualifier in zsh or the ~(N) glob operator in ksh93). Aug 4 at 11:04
  • Question is tagged dash, so why ignore that and address bash and zsh instead? Aug 5 at 7:43
  • 2
    @TobySpeight The user is using dash in a script, yes. It is unclear what the interactive shell is that they are testing things in (their middle code section). My mentioning of bash at the very end is just an added extra.
    – Kusalananda
    Aug 5 at 7:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.