aboutsummaryrefslogtreecommitdiff
path: root/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html
diff options
context:
space:
mode:
authorneodarz <neodarz@neodarz.net>2017-04-28 00:30:19 +0200
committerneodarz <neodarz@neodarz.net>2017-04-28 00:30:19 +0200
commit9a88e9ff0385f66e7c565a394908503dc6e916ad (patch)
tree05ea8b356163f06c5fc99c2caf67fa8d3a28d67d /build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html
parentf1965c50670f611ef54f9471490d45a554f7d866 (diff)
downloadmy_new_personal_website-9a88e9ff0385f66e7c565a394908503dc6e916ad.tar.xz
my_new_personal_website-9a88e9ff0385f66e7c565a394908503dc6e916ad.zip
Site updated at 2017-04-28T00:29:42+02:00
source branch was at: f1965c50670f611ef54f9471490d45a554f7d866 Correct a link
Diffstat (limited to '')
-rw-r--r--build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html69
1 files changed, 69 insertions, 0 deletions
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 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<meta content="pandoc" name="generator"/>
+<meta content="Zhiming Wang" name="author"/>
+<meta content="2015-05-19T18:33:51-07:00" name="date"/>
+<title>Bash: the special slash character in filename expansion</title>
+<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/>
+<meta content="#FFFFFF" name="msapplication-TileColor"/>
+<meta content="/img/favicon-144.png" name="msapplication-TileImage"/>
+<meta content="width=device-width, initial-scale=1" name="viewport"/>
+<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/>
+<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/>
+<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div>
+<nav class="nav">
+<a class="nav-icon" href="/" title="Home"><!--blog icon--></a>
+<a class="nav-title" href="/"><!--blog title--></a>
+<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a>
+</nav>
+<article class="content">
+<header class="article-header">
+<h1 class="article-title">Bash: the special slash character in filename expansion</h1>
+<div class="article-metadata">
+<time class="article-timestamp" datetime="2015-05-19T18:33:51-07:00">May 19, 2015</time>
+</div>
+</header>
+<p>It is well-known and common sense that the slash character (<code>/</code>) serves a special role in Bash filename expansion. For instance, the asterisk <code>*</code> certainly won't match <code>/</code> or <code>.</code> when used in filename expansion; otherwise, a standalone <code>*</code> would match everything in the filesystem.</p>
+<p>However, it is less clear how a literal slash character<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> 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:</p>
+<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">bash-4.3</span>$ shopt -s extglob nullglob
+<span class="ex">bash-4.3</span>$ echo /usr/@(bin<span class="kw">|</span><span class="ex">lib</span>)
+<span class="ex">/usr/bin</span> /usr/lib
+<span class="ex">bash-4.3</span>$ echo /usr@(/bin<span class="kw">|</span><span class="ex">/lib</span>)
+
+<span class="ex">bash-4.3</span>$ [[ /usr/bin == /usr@(/bin<span class="kw">|</span><span class="ex">/lib</span>) ]] <span class="kw">&amp;&amp;</span> <span class="bu">echo</span> matching
+<span class="ex">matching</span></code></pre></div>
+<p>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 <a href="https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching">Bash Reference Manual</a> and the <a href="http://mywiki.wooledge.org/BashGuide/Patterns">Bash Guide</a> but neither mentioned this behavior. One might need to delve into the source code to say for sure what exactly is going on.</p>
+<p>In comparison, Zsh and its <a href="http://zsh.sourceforge.net/Doc/Release/Expansion.html#Filename-Generation">docs</a> are much more up front about this issue:</p>
+<blockquote>
+<p>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). ...</p>
+</blockquote>
+<p>And when we run equivalent code in Zsh:</p>
+<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">zsh-5.0.5$ <span class="kw">setopt</span> NULL_GLOB
+zsh-5.0.5$ <span class="kw">echo</span> /usr/<span class="kw">(</span>bin<span class="kw">|</span>lib<span class="kw">)</span>
+/usr/bin /usr/lib
+zsh-5.0.5$ <span class="kw">echo</span> /usr<span class="kw">(</span>/bin<span class="kw">|</span>/lib<span class="kw">)</span>
+zsh: bad pattern: /usr<span class="kw">(</span>/bin<span class="kw">|</span>/lib<span class="kw">)</span>
+zsh-5.0.5$<span class="kw"> [[</span> /usr/bin <span class="ot">==</span> /usr(/bin|/lib)<span class="kw"> ]]</span> <span class="kw">&amp;&amp;</span> <span class="kw">echo</span> matching
+matching</code></pre></div>
+<p>The lesson? Be careful not to use a pattern like <code>@(path1|path2|path3)</code> 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.</p>
+<div class="footnotes">
+<hr/>
+<ol>
+<li id="fn1"><p>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.<a class="footnotes-backlink" href="#fnref1">↩ī¸Ž</a></p></li>
+</ol>
+</div>
+</article>
+<hr class="content-separator"/>
+<footer class="footer">
+<span class="rfooter">
+<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a>
+<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a>
+</span>
+</footer>
+</body>
+</html>