<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Alias · XB Field Notes</title><link>https://www.xbcatm.com/tags/alias/</link><description>Illustrated field notes on HTTP, DNS, TLS, Caddy, SSH, releases, and recovery.</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://www.xbcatm.com/tags/alias/index.xml" rel="self" type="application/rss+xml"/><item><title>Shell aliases shrink repeated typing</title><link>https://www.xbcatm.com/posts/shell-aliases-shrink-repeated-typing/</link><pubDate>Mon, 04 Oct 2027 00:00:00 +0000</pubDate><guid>https://www.xbcatm.com/posts/shell-aliases-shrink-repeated-typing/</guid><description>An alias maps a short name to a longer command so common sequences become short. Interactive shortcuts are the point; scripts usually avoid them.</description><content:encoded>&lt;p&gt;An alias replaces a command word with shell text while Bash reads a command. It is useful for personal shortcuts such as &lt;code&gt;alias ll='ls -l'&lt;/code&gt;, but it is not an executable and has no independent argument scope. Noninteractive Bash disables alias expansion by default; a script can explicitly enable it. Understanding that distinction explains why a shortcut works at a prompt but disappears in automation.&lt;/p&gt;
&lt;h2 id="replacement-happens-when-input-is-read"&gt;Replacement happens when input is read&lt;/h2&gt;
&lt;p&gt;An unquoted word in command position is eligible for alias expansion. With &lt;code&gt;alias ll='ls -l'&lt;/code&gt;, &lt;code&gt;ll 'two words'&lt;/code&gt; becomes a command whose final argument still contains the space. Aliases do not inherently destroy quoting on arguments supplied by the caller. They simply cannot refer to their own &lt;code&gt;$1&lt;/code&gt; or rearrange a private argument list as functions can.&lt;/p&gt;
&lt;p&gt;The replacement can contain shell syntax, including pipelines or several commands, so aliases are not technically limited to one executable. That freedom also makes their behavior harder to inspect. Bash expands the first word of the replacement again, except when it is the alias already being expanded. Consequently, &lt;code&gt;alias ls='ls -F'&lt;/code&gt; does not recurse forever. A trailing blank in an alias value has another special effect: the following command word is also checked for alias expansion.&lt;/p&gt;
&lt;p&gt;Quoting the definition controls another timing boundary. Single quotes preserve dollar signs for later interpretation in the replacement text; double quotes can expand variables immediately while the alias is being defined. A shortcut meant to follow a changing directory variable can therefore retain an old value. Inspect the stored definition, not just the line originally typed, when diagnosing that discrepancy.&lt;/p&gt;
&lt;h2 id="scope-and-timing-are-different-questions"&gt;Scope and timing are different questions&lt;/h2&gt;
&lt;p&gt;Aliases belong to the current shell; they are not environment variables exported to a separately launched Bash process. A subshell created with parentheses inherits the shell state, which is a different operation. Startup files can define the same alias again, but that is configuration being loaded, not an alias travelling through the environment.&lt;/p&gt;
&lt;p&gt;In Bash, &lt;code&gt;shopt -s expand_aliases&lt;/code&gt; enables expansion in a noninteractive shell. Definitions must still precede the input that uses them. Bash reads a complete line or compound command before executing it, so defining an alias and invoking it later on the same line does not activate that new definition in time. The same issue applies inside a function body being parsed.&lt;/p&gt;
&lt;h2 id="when-it-breaks"&gt;When it breaks&lt;/h2&gt;
&lt;p&gt;A function can capture an alias expansion when its definition is read. Replacing that alias afterward does not rewrite the already parsed function. This surprises users who expect every call to consult the latest alias table. Define functions directly when their behavior should be explicit, and use quoted &lt;code&gt;&amp;quot;$@&amp;quot;&lt;/code&gt; to forward arguments without losing empty values or spaces.&lt;/p&gt;
&lt;p&gt;Another failure is mistaking a shortcut for a command available to another program. A process launcher does not consult your interactive alias table. Diagnose the current shell with &lt;code&gt;type name&lt;/code&gt; and inspect a specific definition with &lt;code&gt;alias name&lt;/code&gt;; remove it with &lt;code&gt;unalias name&lt;/code&gt;. Quoting or backslash-escaping the command word suppresses alias expansion, but functions or builtins can still affect subsequent lookup. An explicit executable path selects that file.&lt;/p&gt;
&lt;h2 id="check-it-quickly"&gt;Check it quickly&lt;/h2&gt;
&lt;p&gt;This Bash experiment uses only diagnostic names and builtins. It intentionally compares disabled expansion, enabled expansion, same-line definition, and a function parsed before an alias changes. Expected failures are captured immediately so a later successful print cannot hide their status.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash --noprofile --norc &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;BASH&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;shopt -u expand_aliases
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;alias demo_alias=&amp;#39;printf &amp;#34;alias=&amp;lt;%s&amp;gt;\n&amp;#34;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_alias hidden 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;printf &amp;#39;disabled=%s\n&amp;#39; &amp;#34;$?&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;shopt -s expand_aliases
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_alias &amp;#39;two words&amp;#39; &amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;alias demo_late=&amp;#39;printf &amp;#34;late\n&amp;#34;&amp;#39;; demo_late 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;printf &amp;#39;same-line=%s\n&amp;#39; &amp;#34;$?&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_late
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;alias demo_version=&amp;#39;printf &amp;#34;old\n&amp;#34;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_function() { demo_version; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;alias demo_version=&amp;#39;printf &amp;#34;new\n&amp;#34;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;demo_version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;unalias demo_alias
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;if command -v demo_alias &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; printf &amp;#39;unexpected command\n&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; printf &amp;#39;alias removed\n&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;fi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;BASH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Expect status &lt;code&gt;127&lt;/code&gt; while expansion is disabled, followed by &lt;code&gt;alias=&amp;lt;two words&amp;gt;&lt;/code&gt; and &lt;code&gt;alias=&amp;lt;&amp;gt;&lt;/code&gt; after enabling it. The same-line call also returns &lt;code&gt;127&lt;/code&gt;; the next line prints &lt;code&gt;late&lt;/code&gt;. The function then prints &lt;code&gt;old&lt;/code&gt;, while a direct invocation prints &lt;code&gt;new&lt;/code&gt;. Finally, lookup confirms removal.&lt;/p&gt;
&lt;p&gt;These results establish the actual boundaries: argument quoting can survive a simple alias, noninteractive expansion is configurable, and read-time substitution can freeze behavior inside a function. For shared scripts, put reusable logic in a function or executable that the script defines or loads explicitly. Keep aliases as visible conveniences for the shell session in which they were configured.&lt;/p&gt;
&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.xbcatm.com/posts/shell-functions-borrow-positional-parameters/"&gt;Shell functions borrow positional parameters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sources"&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tiswww.case.edu/php/chet/bash/bashref.html#Aliases"&gt;Bash reference manual: aliases&lt;/a&gt;, the maintainer-hosted manual on expansion timing and noninteractive behavior, checked 2026-09-07.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_03_01"&gt;POSIX alias substitution&lt;/a&gt;, command-word substitution and quoting rules, checked 2026-09-07.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>