0

Why ./script.sh ? throws No match. ./script.sh is running fine.

script.sh

#!/bin/sh
echo "Hello World"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
spiderman
  • 337
  • 1
  • 3
  • 10
  • 1
    Your calling shell (not the one running your script) is trying to look for files with single-character names. `?` is a glob character. – Charles Duffy Nov 30 '15 at 23:09
  • ...to be very clear, btw, this error is being thrown by the interactive shell into which you're typing `./script ?`, not the separate copy of `/bin/sh` that would be started if your `script.sh` were successfully invoked. Thus, your script isn't actually starting at all; one could thus argue that this isn't a problem with your script, but a usage problem in understanding your interactive shell. – Charles Duffy Nov 30 '15 at 23:13
  • Arguably, this might be a duplicate of http://stackoverflow.com/questions/11456403/stop-shell-wildcard-character-expansion – Charles Duffy Dec 01 '15 at 00:20
  • To be very pedantic, one could argue that your script isn't actually exiting in this case: When your shell has `failglob` enabled (as is evidently the case here), any command containing a non-matching glob isn't invoked at all! – Charles Duffy Dec 01 '15 at 00:42

1 Answers1

0

? is a glob character on UNIX. By default, in POSIX shells, a glob that matches no files at all will evaluate to itself; however, many shells have the option to modify this behavior and either pass no arguments in this case or make it an error.

If you want to pass this (or any other string which can be interpreted as a glob) literally, quote it:

./script.sh '?'

If you didn't use quotes, consider what the following would do:

touch a b c
./script.sh ?   ## this is the same as running: ./script.sh a b c

That said -- the behavior of your outer shell (exiting when no matches exist, rather than defaulting to pass the non-matching glob expression as a literal) is non-default. If this shell is bash, you can modify it with:

shopt -u failglob

Note, however, that this doesn't really fix your problem, but only masks it when your current directory has no single-character filenames. The only proper fix is to correct your usage to quote and escape values properly.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • * is also UNIX glob character. But * works fine. How ./script.sh * runs without No match issue? – spiderman Nov 30 '15 at 23:25
  • @spiderman, because `*` actually matches things, whereas when you reproduce this exact issue you have no files in the current directory that match `?`. If you look at `$1`, you'll see that it doesn't contain a literal `*`, but instead a filename. – Charles Duffy Nov 30 '15 at 23:43
  • My answer tells you: You need to quote or otherwise escape it. There's nothing the script can do: Glob expansion is performed by the outer shell (the one you're typing `./script.sh ?` into) **before** the script starts to run; by the time it's invoked, it's too late to change anything. – Charles Duffy Dec 01 '15 at 00:15
  • BTW, this is part of why UNIX people frown so much on people trying to use the Windows convention of passing `?` or `-?` to request help. Using `-h` or `--help` avoids this class of problem entirely. – Charles Duffy Dec 01 '15 at 00:17
  • ...of course, you could also turn off glob expansion entirely in the calling shell (with `set -f`) before trying to run the script, but no commands involving globs would then work until this were reversed with `set +f`. – Charles Duffy Dec 01 '15 at 00:19