Fedora 31 and Debian 10 behaves different when I run the following command:
/bin/ls /bin/!(znew) | /bin/grep znew
Fedora it outputs nothing, but Debian it does:
znew
znew
exists on Fedora, if I run /bin/ls /bin/znew | /bin/grep znew
I get:
/bin/znew
(On Debian it happens the same thing)
I've checked bash configuration on both distros, the only difference I've found is that on Fedora I have:
cdable_vars on
cdspell on
dirspell on
login_shell on
On Debian those options are disabled, and extglob
is on on both distros
Note: Command grep
it's only used here to make the listing shorter
Versions:
-
On Fedora: 5.0.11
-
On Debian: 5.0-4
Why does it exist such a difference?
UPDATE 1
/bin is a symlink to /usr/bin on both Debian and Fedora.
This is the output of searching for znew string in filenames:
updatedb && locate znew
/usr/bin/znew
/usr/share/man/man1/znew.1.gz
/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/19.08/5a35247ad1c941455f2f9c4139d9136c6c0662e1b04e5b3c56121e7f67ba0100/files/bin/znew
/var/lib/lxc/centos/rootfs/usr/bin/znew
/var/lib/lxc/centos/rootfs/usr/share/man/man1/znew.1.gz
/var/lib/lxc/opensuse/rootfs/usr/bin/xznew
/var/lib/lxc/opensuse/rootfs/usr/bin/znew
/var/lib/lxc/opensuse/rootfs/usr/share/man/man1/xznew.1.gz
/var/lib/lxc/opensuse/rootfs/usr/share/man/man1/znew.1.gz
UPDATE 2
I've find something interesting, there was in Debian a symlink of /bin/X11 pointing to .
after removing it behaves as in Fedora.
Best Answer
Given that the
extglob
shell option is set in your interactivebash
session, the commandwould first run
ls
with all the names in/bin
that is notznew
as arguments. If this list of names includes names of subdirectories,ls
would output the contents of those subdirectories (since-d
was not used withls
). If one of these subdirectories contain the nameznew
, then thegrep
would match and output that name.The contents of the unknown subdirectory of
/bin
would be listed byls
without prepending the names in it with any directory path. Hence, if a subdirectory contains theznew
name, it would be outputted asznew
rather than as/bin/some-dir/znew
.When
ls
is used as init would output the string
/bin/znew
rather thanznew
(if that pathname exists). It does this because it is outputting the specific pathname of a file given as a command line argument, not the contents of a directory given as an argument.A situation like this could possibly have occurred if someone tried to create a symbolic link for
/usr/bin
called/bin
while/bin
was already a symbolic link to/usr/bin
, or while/bin
was still a directory.In an update to the question, it is revealed that
/bin/X11
was a symbolic link to.
(the current directory). This means thatznew
would have been accessible through the pathname/bin/X11/znew
.So, in conclusion, what is happening is that the
/bin/!(znew)
globbing pattern expanded to a list of pathnames, one of these being/bin/X11
(but not/bin/znew
). Thels
utility would then get all pathnames, including/bin/X11
as arguments. Whenls
gets to list/bin/X11
, the contents of the/bin
directory is listed, due to/bin/X11
pointing there. Thegrep
utility then picks outznew
, which will part of the output ofls
.As Stéphane Chazelas points out in comments, you would get the same effect if there is a file in
/bin
on your Debian system that has a name containing a newline followed by the stringznew
(possibly followed by another newline and maybe further characters).Since the name is not exactly the string
znew
, it would match the pattern/bin/!(znew)
andls
would output this single name asand
grep
would extractznew
from that output.