From 9a88e9ff0385f66e7c565a394908503dc6e916ad Mon Sep 17 00:00:00 2001 From: neodarz Date: Fri, 28 Apr 2017 00:30:19 +0200 Subject: Site updated at 2017-04-28T00:29:42+02:00 source branch was at: f1965c50670f611ef54f9471490d45a554f7d866 Correct a link --- ...cial-slash-character-in-filename-expansion.html | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html (limited to 'build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html') diff --git a/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html b/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html new file mode 100644 index 00000000..580272ae --- /dev/null +++ b/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html @@ -0,0 +1,69 @@ + + + + + + + +Bash: the special slash character in filename expansion + + + + + + + + + +
This blog has been archived.
Visit my home page at zhimingwang.org.
+ +
+
+

Bash: the special slash character in filename expansion

+ +
+

It is well-known and common sense that the slash character (/) serves a special role in Bash filename expansion. For instance, the asterisk * certainly won't match / or . when used in filename expansion; otherwise, a standalone * would match everything in the filesystem.

+

However, it is less clear how a literal slash character1 is treated in extended glob patterns. Naively one would expect it to just match a literal slash, but the real situtation is more complicated than that. Consider the following examples:

+
bash-4.3$ shopt -s extglob nullglob
+bash-4.3$ echo /usr/@(bin|lib)
+/usr/bin /usr/lib
+bash-4.3$ echo /usr@(/bin|/lib)
+
+bash-4.3$ [[ /usr/bin == /usr@(/bin|/lib) ]] && echo matching
+matching
+

As seen from this example, patterns with slash simply doesn't work (in filename expansion) when placed in an extended glob pattern list, and there's no error whatsoever. I looked up the Bash Reference Manual and the Bash Guide but neither mentioned this behavior. One might need to delve into the source code to say for sure what exactly is going on.

+

In comparison, Zsh and its docs are much more up front about this issue:

+
+

Note that grouping cannot extend over multiple directories: it is an error to have a ‘/’ within a group (this only applies for patterns used in filename generation). ...

+
+

And when we run equivalent code in Zsh:

+
zsh-5.0.5$ setopt NULL_GLOB
+zsh-5.0.5$ echo /usr/(bin|lib)
+/usr/bin /usr/lib
+zsh-5.0.5$ echo /usr(/bin|/lib)
+zsh: bad pattern: /usr(/bin|/lib)
+zsh-5.0.5$ [[ /usr/bin == /usr(/bin|/lib) ]] && echo matching
+matching
+

The lesson? Be careful not to use a pattern like @(path1|path2|path3) in Bash when the paths are absolute, or relative but contain the slash. Unlike Zsh, Bash just silently fails on a pattern like this, which is rather dangerous in scripts.

+
+
+
    +
  1. Here, "a literal slash character" also applies to one that comes from tilde expansion, parameter expansion or command substitution, since they are performed before filename expansion in Bash.↩ī¸Ž

  2. +
+
+
+
+ + + -- cgit v1.2.1