Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -fcf-protection -O2 -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -g -D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -Wuninitialized -Wextra -Wno-switch-enum -Wno-unused-variable -Wno-unused-parameter -Wno-parentheses -ftree-loop-linear -pipe -DBNC382214=0 -DIMPORT_FUNCTIONS_DEF=0 -DDEFAULT_LOADABLE_BUILTINS_PATH='/usr/lib64/bash' uname output: Linux uefi 7.0.10-2-default #1 SMP PREEMPT_DYNAMIC Sat May 23 12:09:09 UTC 2026 (bb95589) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu

Bash Version: 5.3
Patch Level: 9
Release Status: release

Description:

Consider:

$ ls *
*  x
$

So, two files - the first with the name '*', the second irrelevant.

$ bar='\**'
$ ls $bar
*
$

So far so good - pathname expansion produces expected result. In the pattern "\*" matches the literal "*".

$ bar='\*'
$ ls $bar
ls: cannot access '\*': No such file or directory
$

Oops. Why it suddenly attempts to match *two* characters "\*" instead of just one literal "*"?

It is even more confusing as in other places where patterns are used the "\*" pattern apparently works correctly:

$ foo='abc:*'
$ echo ${foo%:$bar}
abc
$ [[ $foo == abc:$bar ]] && echo yes || echo no
yes
$


Repeat-By:

Assign a glob pattern with all special characters escaped by the backslash ('\') and use this variable on the command line. Observe that shell does not remove backslashes from the pattern so the result does not match the existing files.

$ touch '***'
$ foo='\*\*\*'
$ ls $foo
ls: cannot access '\*\*\*': No such file or directory
$ ls '***'
***
$

Reply via email to