0

For example, in rm -r abc* "*" means any string. However, if we use it in touch abc* abcd* abcde* (and we don't have any files in directory starting with abc or abcd or abcde) "*" means just a symbol, and files abc* abcd* abcde* will be created. If after that we will use touch -m ab* the modification time of files abc* abcd* abcde* will be changed.

Why in some cases "*" means any string, and in some cases it is just a symbol? how the computer know when to change it's meaning?

  • 3
    It's only a literal "*" when it doesn't match anything. That behavior can be changed in bash with shopt -s nullglob. – jordanm Sep 30 '19 at 21:50
  • 1
    It works the same way actually, as rm abc* where there is no file matching abc* will give the error message rm: cannot remove 'abc*': No such file or directory. So if there is no match (whatever the command) the * will be just a symbol. Hence your question title is incorrect. – wurtel Oct 1 '19 at 7:12
  • Important to note that the external commands have nothing to do with it: the shell handles globbing before lauching the command: see 3.1.1 Shell Operation – glenn jackman Oct 1 '19 at 16:07
7

When a pattern such as abc* is used unquoted in the shell, the shell will try to match it against the available filenames (this is called "filename generation" but is often referred to as "globbing"). If it fails to match any filename, most sh-like shells will leave the pattern unexpanded and pass it to the utility as is.

Example:

$ touch xyz
$ touch abc*
$ tree
.
|-- abc*
`-- xyz

0 directory, 2 files
$ touch xyz*
$ tree
.
|-- abc*
`-- xyz

0 directory, 2 files

The touch xyz* command did not create a file called xyz*, because the filename xyz matched the pattern. The touch utility was therefore called with the xyz filename.

In the bash shell, setting the failglob shell option with shopt -s failglob will make the shell complain if a shell glob does not match anything:

$ shopt -s failglob
$ touch 123*
bash: no match: 123*

The equivalent option is turned on by default in the zsh shell.

Setting the nullglob shell option in bash (or NULL_GLOB in zsh) would make the pattern disappear if it doesn't match a filename:

$ shopt -s nullglob
$ touch fo*
usage: touch [-acm] [-d ccyy-mm-ddTHH:MM:SS[.frac][Z]] [-r file]
             [-t [[cc]yy]mmddHHMM[.SS]] file ...

(we get an error from touch since it was called without any arguments)

To guarantee that the pattern is used as a string (as it is), and not used for globbing, you should quote it:

$ touch "file*"
$ touch "file**"
$ touch "file***"
$ tree
.
|-- file*
|-- file**
`-- file***

0 directory, 3 files

Not quoting the filenames in this example would have given you only one file called file* (if the directory was initially empty), since the file** and file*** patterns matches that first file* name.

| improve this answer | |
  • most shells should be most Bourne-like shells. That's a misfeature introduced by the Bourne shell, shells before the Bourne shell didn't have that issue and most non-Bourne-like shells (csh, tcsh, fish, (zsh)) don't have the problem. – Stéphane Chazelas Oct 1 '19 at 7:33

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.