<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Scripting on Software Engineering Learning Paths</title><link>https://kyngo.github.io/learning-paths/paths/scripting/</link><description>Recent content in Scripting on Software Engineering Learning Paths</description><generator>Hugo</generator><language>en</language><atom:link href="https://kyngo.github.io/learning-paths/paths/scripting/index.xml" rel="self" type="application/rss+xml"/><item><title>Shell Basics</title><link>https://kyngo.github.io/learning-paths/paths/scripting/01-shell-basics/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/01-shell-basics/</guid><description>&lt;h2 id="what-is-a-shell"&gt;What is a Shell?&lt;a class="anchor" href="#what-is-a-shell"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A shell is a command-line interpreter — a program that reads text commands, interprets them, and executes them by calling the operating system&amp;rsquo;s kernel. It serves two roles: an interactive environment for running commands one at a time, and a programming language for automating sequences of commands.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 User[&amp;#34;User Input&amp;#34;] --&amp;gt; Shell[&amp;#34;Shell (bash, zsh)&amp;#34;]
 Shell --&amp;gt; Kernel[&amp;#34;OS Kernel&amp;#34;]
 Kernel --&amp;gt; HW[&amp;#34;Hardware&amp;#34;]
 Kernel --&amp;gt; FS[&amp;#34;File System&amp;#34;]
 Kernel --&amp;gt; Net[&amp;#34;Network&amp;#34;]
 Shell --&amp;gt; Output[&amp;#34;Output (stdout/stderr)&amp;#34;]&lt;/pre&gt;&lt;p&gt;The shell is NOT the terminal. The terminal is the window application (iTerm2, GNOME Terminal). The shell is the program running inside it.&lt;/p&gt;</description></item><item><title>Variables, Quoting, and Expansion</title><link>https://kyngo.github.io/learning-paths/paths/scripting/02-variables-quoting-expansion/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/02-variables-quoting-expansion/</guid><description>&lt;h2 id="variables"&gt;Variables&lt;a class="anchor" href="#variables"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Shell variables are untyped — everything is a string. The shell interprets context to decide if something is a number or text.&lt;/p&gt;
&lt;h3 id="assignment-rules"&gt;Assignment Rules&lt;a class="anchor" href="#assignment-rules"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Correct — NO spaces around =&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/usr/local/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# WRONG — spaces cause errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Error: &amp;#34;name: command not found&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="variable-usage"&gt;Variable Usage&lt;a class="anchor" href="#variable-usage"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Hello, world&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Same — braces for clarity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_backup&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# world_backup (braces needed here)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$name_backup&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Empty! (looks for variable name_backup)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="variable-types"&gt;Variable Types&lt;a class="anchor" href="#variable-types"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Regular variable (local to current shell/script)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Environment variable (inherited by child processes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;abc123&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Readonly (constant)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="nv"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# Error: readonly variable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Unset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;unset&lt;/span&gt; greeting &lt;span class="c1"&gt;# removes the variable&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="special-variables"&gt;Special Variables&lt;a class="anchor" href="#special-variables"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$0&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Script name&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$1&lt;/code&gt;-&lt;code&gt;$9&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Positional parameters&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Number of arguments&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;All arguments (as separate words)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;All arguments (as single string)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Exit code of last command&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Current process PID&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;PID of last background process&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="quoting"&gt;Quoting&lt;a class="anchor" href="#quoting"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Quoting is the #1 source of shell scripting bugs. Understanding it prevents most issues.&lt;/p&gt;</description></item><item><title>Control Structures</title><link>https://kyngo.github.io/learning-paths/paths/scripting/03-control-structures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/03-control-structures/</guid><description>&lt;h2 id="conditionals-ifelifelse"&gt;Conditionals: if/elif/else&lt;a class="anchor" href="#conditionals-ifelifelse"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;active&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Service is running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;stopped&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Service is stopped&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unknown status: &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The semicolon before &lt;code&gt;then&lt;/code&gt; replaces a newline — these are equivalent:&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;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; condition &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; command&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; condition &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="test-commands---vs--"&gt;Test Commands: &lt;code&gt;[[ ]]&lt;/code&gt; vs &lt;code&gt;[ ]&lt;/code&gt;&lt;a class="anchor" href="#test-commands---vs--"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="---bash-extended-test-preferred"&gt;&lt;code&gt;[[ ]]&lt;/code&gt; — Bash Extended Test (Preferred)&lt;a class="anchor" href="#---bash-extended-test-preferred"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Category&lt;/th&gt;
					&lt;th&gt;Operator&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;String&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Equal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;String&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Not equal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;String&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;=~&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Regex match&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;String&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-z &amp;quot;$s&amp;quot;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;String is empty&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;String&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-n &amp;quot;$s&amp;quot;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;String is non-empty&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Numeric&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;, &lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Equal, not equal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Numeric&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;, &lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Less than, less or equal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Numeric&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;, &lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Greater than, greater or equal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-f&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Is regular file&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Is directory&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-e&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Exists (any type)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-r&lt;/code&gt;, &lt;code&gt;-w&lt;/code&gt;, &lt;code&gt;-x&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Readable, writable, executable&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-s&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Exists and non-empty&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Logic&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;AND&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Logic&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;||&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;OR&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Logic&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;NOT&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="--vs---comparison"&gt;&lt;code&gt;[ ]&lt;/code&gt; vs &lt;code&gt;[[ ]]&lt;/code&gt; Comparison&lt;a class="anchor" href="#--vs---comparison"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th style="text-align: center"&gt;&lt;code&gt;[ ]&lt;/code&gt; (POSIX)&lt;/th&gt;
					&lt;th style="text-align: center"&gt;&lt;code&gt;[[ ]]&lt;/code&gt; (Bash)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Word splitting on vars&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Yes (must quote!)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;No&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Glob expansion&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Yes&lt;/td&gt;
					&lt;td style="text-align: center"&gt;No&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Regex (&lt;code&gt;=~&lt;/code&gt;)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pattern matching (&lt;code&gt;==&lt;/code&gt; with &lt;code&gt;*&lt;/code&gt;)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt; inside&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Portability&lt;/td&gt;
					&lt;td style="text-align: center"&gt;All shells&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Bash/Zsh only&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; Use &lt;code&gt;[[ ]]&lt;/code&gt; in bash scripts. Use &lt;code&gt;[ ]&lt;/code&gt; only for POSIX portability.&lt;/p&gt;</description></item><item><title>Functions</title><link>https://kyngo.github.io/learning-paths/paths/scripting/04-functions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/04-functions/</guid><description>&lt;h2 id="defining-functions"&gt;Defining Functions&lt;a class="anchor" href="#defining-functions"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="c1"&gt;# Standard syntax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;greet&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:?Error: name required&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;Hello&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alternative syntax (less common)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; greet &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;function&lt;/code&gt; keyword is optional in bash. Prefer the &lt;code&gt;name()&lt;/code&gt; syntax — it&amp;rsquo;s POSIX-compatible.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="parameters-and-return-values"&gt;Parameters and Return Values&lt;a class="anchor" href="#parameters-and-return-values"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="positional-parameters"&gt;Positional Parameters&lt;a class="anchor" href="#positional-parameters"&gt;#&lt;/a&gt;&lt;/h3&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;create_user&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;viewer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# default value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Creating &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="s2"&gt;) with role: &lt;/span&gt;&lt;span class="nv"&gt;$role&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;create_user &lt;span class="s2"&gt;&amp;#34;alice&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;alice@example.com&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;create_user &lt;span class="s2"&gt;&amp;#34;bob&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;bob@example.com&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# role defaults to &amp;#34;viewer&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="parameter-validation"&gt;Parameter Validation&lt;a class="anchor" href="#parameter-validation"&gt;#&lt;/a&gt;&lt;/h3&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;deploy&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:?Error: environment required (test|pre|prod)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:?Error: version required&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$env&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;(&lt;/span&gt;test&lt;span class="p"&gt;|&lt;/span&gt;pre&lt;span class="p"&gt;|&lt;/span&gt;prod&lt;span class="o"&gt;)&lt;/span&gt;$ &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Invalid environment: &lt;/span&gt;&lt;span class="nv"&gt;$env&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Deploying v&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$env&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="return-values"&gt;Return Values&lt;a class="anchor" href="#return-values"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Functions return exit codes (0-255), not data. Use &lt;code&gt;echo&lt;/code&gt; + command substitution for data:&lt;/p&gt;</description></item><item><title>Text Processing</title><link>https://kyngo.github.io/learning-paths/paths/scripting/05-text-processing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/05-text-processing/</guid><description>&lt;h2 id="the-big-three-grep-sed-awk"&gt;The Big Three: grep, sed, awk&lt;a class="anchor" href="#the-big-three-grep-sed-awk"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These three tools handle 90% of text processing needs on any Unix system:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
					&lt;th&gt;Think of it as&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;grep&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Find lines matching a pattern&lt;/td&gt;
					&lt;td&gt;Filter&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;sed&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Transform text (find &amp;amp; replace)&lt;/td&gt;
					&lt;td&gt;Editor&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;awk&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Process structured/columnar data&lt;/td&gt;
					&lt;td&gt;Spreadsheet&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 Input[&amp;#34;Input Text&amp;#34;] --&amp;gt; grep[&amp;#34;grep: FIND&amp;#34;]
 Input --&amp;gt; sed[&amp;#34;sed: TRANSFORM&amp;#34;]
 Input --&amp;gt; awk[&amp;#34;awk: PROCESS&amp;#34;]
 grep --&amp;gt; Lines[&amp;#34;Matching lines&amp;#34;]
 sed --&amp;gt; Modified[&amp;#34;Modified text&amp;#34;]
 awk --&amp;gt; Computed[&amp;#34;Computed results&amp;#34;]&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="grep--search-for-patterns"&gt;grep — Search for Patterns&lt;a class="anchor" href="#grep--search-for-patterns"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="basic-usage"&gt;Basic Usage&lt;a class="anchor" href="#basic-usage"&gt;#&lt;/a&gt;&lt;/h3&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;grep &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# lines containing &amp;#34;error&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -i &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# case-insensitive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -n &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# show line numbers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -c &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# count matches&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -l &lt;span class="s2"&gt;&amp;#34;TODO&amp;#34;&lt;/span&gt; src/*.py &lt;span class="c1"&gt;# list files with matches&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -L &lt;span class="s2"&gt;&amp;#34;test&amp;#34;&lt;/span&gt; src/*.py &lt;span class="c1"&gt;# list files WITHOUT matches&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -v &lt;span class="s2"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# invert (exclude matches)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -r &lt;span class="s2"&gt;&amp;#34;TODO&amp;#34;&lt;/span&gt; src/ &lt;span class="c1"&gt;# recursive search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -w &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; logfile.txt &lt;span class="c1"&gt;# whole word only&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="extended-regex--e"&gt;Extended Regex (&lt;code&gt;-E&lt;/code&gt;)&lt;a class="anchor" href="#extended-regex--e"&gt;#&lt;/a&gt;&lt;/h3&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;grep -E &lt;span class="s2"&gt;&amp;#34;error|warning|critical&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# alternation (OR)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -E &lt;span class="s2"&gt;&amp;#34;^[0-9]{4}-[0-9]{2}&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# lines starting with date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -E &lt;span class="s2"&gt;&amp;#34;HTTP/[12]\.[01]\&amp;#34; [45]&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# 4xx/5xx responses&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -oE &lt;span class="s2"&gt;&amp;#34;[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# extract IPs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="common-patterns"&gt;Common Patterns&lt;a class="anchor" href="#common-patterns"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Find function definitions in Python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -rn &lt;span class="s2"&gt;&amp;#34;^def &amp;#34;&lt;/span&gt; src/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Find TODO/FIXME comments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -rn &lt;span class="s2"&gt;&amp;#34;TODO\|FIXME\|HACK&amp;#34;&lt;/span&gt; --include&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Count errors per log file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -c &lt;span class="s2"&gt;&amp;#34;ERROR&amp;#34;&lt;/span&gt; /var/log/*.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Lines between two patterns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -A5 &lt;span class="s2"&gt;&amp;#34;Exception&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# 5 lines After match&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -B3 &lt;span class="s2"&gt;&amp;#34;Exception&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# 3 lines Before match&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -C2 &lt;span class="s2"&gt;&amp;#34;Exception&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# 2 lines Context (before + after)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="sed--stream-editor"&gt;sed — Stream Editor&lt;a class="anchor" href="#sed--stream-editor"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="substitution-most-common-use"&gt;Substitution (Most Common Use)&lt;a class="anchor" href="#substitution-most-common-use"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Replace first occurrence per line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;s/old/new/&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Replace ALL occurrences per line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;s/old/new/g&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Case-insensitive replace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;s/error/ERROR/gi&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# In-place editing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -i &lt;span class="s1"&gt;&amp;#39;s/old/new/g&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -i &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;s/old/new/g&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# macOS (requires empty string)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="line-operations"&gt;Line Operations&lt;a class="anchor" href="#line-operations"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Delete lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;/^#/d&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# delete comment lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;/^$/d&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# delete empty lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;1,5d&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# delete lines 1-5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Print specific lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -n &lt;span class="s1"&gt;&amp;#39;10,20p&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# print lines 10-20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -n &lt;span class="s1"&gt;&amp;#39;/START/,/END/p&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# print between patterns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Insert/append&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;1i\Header line&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# insert before line 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;$a\Footer line&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# append after last line&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="practical-examples"&gt;Practical Examples&lt;a class="anchor" href="#practical-examples"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Remove trailing whitespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;s/[[:space:]]*$//&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Replace environment variable placeholders&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s2"&gt;&amp;#34;s/\${DB_HOST}/&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;/g&amp;#34;&lt;/span&gt; template.conf &amp;gt; config.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Comment out a line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -i &lt;span class="s1"&gt;&amp;#39;/dangerous_setting/s/^/# /&amp;#39;&lt;/span&gt; config.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Extract value from key=value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -n &lt;span class="s1"&gt;&amp;#39;s/^version=//p&amp;#39;&lt;/span&gt; config.ini&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="multiple-operations"&gt;Multiple Operations&lt;a class="anchor" href="#multiple-operations"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Chain with -e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -e &lt;span class="s1"&gt;&amp;#39;s/foo/bar/g&amp;#39;&lt;/span&gt; -e &lt;span class="s1"&gt;&amp;#39;s/baz/qux/g&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Or use semicolons&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed &lt;span class="s1"&gt;&amp;#39;s/foo/bar/g; s/baz/qux/g&amp;#39;&lt;/span&gt; file&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="awk--pattern-scanning-and-processing"&gt;awk — Pattern Scanning and Processing&lt;a class="anchor" href="#awk--pattern-scanning-and-processing"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="column-extraction"&gt;Column Extraction&lt;a class="anchor" href="#column-extraction"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Print specific columns (whitespace-delimited)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print $1, $3}&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Custom delimiter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk -F&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; data.csv &lt;span class="c1"&gt;# CSV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk -F&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt; /etc/passwd &lt;span class="c1"&gt;# colon-separated&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="filtering"&gt;Filtering&lt;a class="anchor" href="#filtering"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Where clause (column conditions)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;$3 &amp;gt; 100 {print $1, $3}&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;$2 == &amp;#34;ERROR&amp;#34; {print}&amp;#39;&lt;/span&gt; log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;NF &amp;gt; 3&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# lines with more than 3 fields&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;length &amp;gt; 80&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# lines longer than 80 chars&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="built-in-variables"&gt;Built-in Variables&lt;a class="anchor" href="#built-in-variables"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$0&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Entire line&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$1&lt;/code&gt;-&lt;code&gt;$N&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Field N&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Current line number&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NF&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Number of fields in current line&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;FS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Field separator (input)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;OFS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Output field separator&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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;&lt;span class="c1"&gt;# Number lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print NR&amp;#34;: &amp;#34;$0}&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Print last field&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print $NF}&amp;#39;&lt;/span&gt; file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Print second-to-last field&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print $(NF-1)}&amp;#39;&lt;/span&gt; file&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="aggregation"&gt;Aggregation&lt;a class="anchor" href="#aggregation"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Sum a column&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{sum += $2} END {print &amp;#34;Total:&amp;#34;, sum}&amp;#39;&lt;/span&gt; sales.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Average&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{sum += $2; n++} END {print &amp;#34;Avg:&amp;#34;, sum/n}&amp;#39;&lt;/span&gt; data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Count by category&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{count[$1]++} END {for (k in count) print k, count[k]}&amp;#39;&lt;/span&gt; log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Max value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;BEGIN{max=0} $3&amp;gt;max{max=$3} END{print &amp;#34;Max:&amp;#34;, max}&amp;#39;&lt;/span&gt; data.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="begin-and-end-blocks"&gt;BEGIN and END Blocks&lt;a class="anchor" href="#begin-and-end-blocks"&gt;#&lt;/a&gt;&lt;/h3&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;awk &lt;span class="s1"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;BEGIN { FS=&amp;#34;,&amp;#34;; OFS=&amp;#34;\t&amp;#34;; print &amp;#34;Name\tAge\tCity&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;NR &amp;gt; 1 { print $1, $2, $3 }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;END { print &amp;#34;---&amp;#34;; print NR-1, &amp;#34;records processed&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; data.csv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="cut-sort-uniq--simple-but-powerful"&gt;cut, sort, uniq — Simple but Powerful&lt;a class="anchor" href="#cut-sort-uniq--simple-but-powerful"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="cut--extract-columns"&gt;cut — Extract Columns&lt;a class="anchor" href="#cut--extract-columns"&gt;#&lt;/a&gt;&lt;/h3&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;cut -d&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt; -f1,3 data.csv &lt;span class="c1"&gt;# fields 1 and 3, comma-delimited&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cut -d&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt; -f1 /etc/passwd &lt;span class="c1"&gt;# usernames&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cut -c1-10 file &lt;span class="c1"&gt;# characters 1-10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sort"&gt;sort&lt;a class="anchor" href="#sort"&gt;#&lt;/a&gt;&lt;/h3&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;sort file &lt;span class="c1"&gt;# alphabetical&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort -n file &lt;span class="c1"&gt;# numeric&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort -k2 -t&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt; file &lt;span class="c1"&gt;# by field 2, comma-delimited&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort -r file &lt;span class="c1"&gt;# reverse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort -u file &lt;span class="c1"&gt;# unique (deduplicate)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort -h file &lt;span class="c1"&gt;# human-readable numbers (1K, 2M)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="uniq-requires-sorted-input"&gt;uniq (requires sorted input)&lt;a class="anchor" href="#uniq-requires-sorted-input"&gt;#&lt;/a&gt;&lt;/h3&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;sort file &lt;span class="p"&gt;|&lt;/span&gt; uniq &lt;span class="c1"&gt;# remove duplicates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort file &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="c1"&gt;# count occurrences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort file &lt;span class="p"&gt;|&lt;/span&gt; uniq -d &lt;span class="c1"&gt;# show only duplicates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort file &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; sort -rn &lt;span class="c1"&gt;# frequency ranking&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="combining-tools"&gt;Combining Tools&lt;a class="anchor" href="#combining-tools"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="c1"&gt;# Top 10 IP addresses in access log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt; access.log &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; sort -rn &lt;span class="p"&gt;|&lt;/span&gt; head -10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Count HTTP status codes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;{print $9}&amp;#39;&lt;/span&gt; access.log &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; sort -rn
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Find largest files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f -exec du -h &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort -rh &lt;span class="p"&gt;|&lt;/span&gt; head -20
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Extract unique error messages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep &lt;span class="s2"&gt;&amp;#34;ERROR&amp;#34;&lt;/span&gt; app.log &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.*ERROR //&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort -u&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="key-takeaways"&gt;Key Takeaways&lt;a class="anchor" href="#key-takeaways"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;grep finds, sed transforms, awk processes&lt;/strong&gt; — know which to reach for&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;grep -E&lt;/strong&gt; for extended regex (alternation, quantifiers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sed &amp;rsquo;s/old/new/g&amp;rsquo;&lt;/strong&gt; for find-and-replace (add &lt;code&gt;-i&lt;/code&gt; for in-place)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;awk &amp;lsquo;{print $N}&amp;rsquo;&lt;/strong&gt; for column extraction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sort | uniq -c | sort -rn&lt;/strong&gt; is the frequency analysis pattern&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Combine tools with pipes&lt;/strong&gt; — each does one thing well&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Pipes, Redirection, and Process Substitution</title><link>https://kyngo.github.io/learning-paths/paths/scripting/06-pipes-redirection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/06-pipes-redirection/</guid><description>&lt;h2 id="the-unix-philosophy"&gt;The Unix Philosophy&lt;a class="anchor" href="#the-unix-philosophy"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;Write programs that do one thing and do it well. Write programs to work together.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Pipes are how you connect small tools into powerful workflows.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;cat log&amp;#34;] --&amp;gt;|pipe| B[&amp;#34;grep ERROR&amp;#34;]
 B --&amp;gt;|pipe| C[&amp;#34;awk &amp;#39;{print $4}&amp;#39;&amp;#34;]
 C --&amp;gt;|pipe| D[&amp;#34;sort&amp;#34;]
 D --&amp;gt;|pipe| E[&amp;#34;uniq -c&amp;#34;]
 E --&amp;gt;|pipe| F[&amp;#34;sort -rn&amp;#34;]
 F --&amp;gt;|pipe| G[&amp;#34;head -10&amp;#34;]&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="pipes-"&gt;Pipes (&lt;code&gt;|&lt;/code&gt;)&lt;a class="anchor" href="#pipes-"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Connect stdout of one command to stdin of the next:&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;&lt;span class="c1"&gt;# Top 10 error sources from a log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat access.log &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;ERROR&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $4}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; sort -rn &lt;span class="p"&gt;|&lt;/span&gt; head -10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Count unique users currently logged in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;who &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort -u &lt;span class="p"&gt;|&lt;/span&gt; wc -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Find largest directories&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;du -sh */ &lt;span class="p"&gt;|&lt;/span&gt; sort -rh &lt;span class="p"&gt;|&lt;/span&gt; head -5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pipe-behavior"&gt;Pipe Behavior&lt;a class="anchor" href="#pipe-behavior"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Each command in a pipe runs as a separate process&lt;/li&gt;
&lt;li&gt;They run &lt;strong&gt;concurrently&lt;/strong&gt; (not sequentially)&lt;/li&gt;
&lt;li&gt;Data flows as a stream — no temp files needed&lt;/li&gt;
&lt;li&gt;If any command in the pipe exits, the others receive SIGPIPE&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="file-descriptors"&gt;File Descriptors&lt;a class="anchor" href="#file-descriptors"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every process has three standard streams:&lt;/p&gt;</description></item><item><title>File Operations and Permissions</title><link>https://kyngo.github.io/learning-paths/paths/scripting/07-file-operations-permissions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/07-file-operations-permissions/</guid><description>&lt;h2 id="file-operations"&gt;File Operations&lt;a class="anchor" href="#file-operations"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="creating-files-and-directories"&gt;Creating Files and Directories&lt;a class="anchor" href="#creating-files-and-directories"&gt;#&lt;/a&gt;&lt;/h3&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;touch file.txt &lt;span class="c1"&gt;# create empty file (or update timestamp)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir mydir &lt;span class="c1"&gt;# create directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p path/to/nested/dir &lt;span class="c1"&gt;# create parent dirs as needed&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="copying-moving-deleting"&gt;Copying, Moving, Deleting&lt;a class="anchor" href="#copying-moving-deleting"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Copy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp source.txt dest.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp -r source_dir/ dest_dir/ &lt;span class="c1"&gt;# recursive (directories)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp -p file.txt backup/ &lt;span class="c1"&gt;# preserve permissions and timestamps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Move / Rename&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv old_name.txt new_name.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv file.txt /other/directory/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm file.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -r directory/ &lt;span class="c1"&gt;# recursive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -f file.txt &lt;span class="c1"&gt;# force (no error if missing)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf directory/ &lt;span class="c1"&gt;# recursive + force (DANGEROUS)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="safety-with-rm"&gt;Safety with &lt;code&gt;rm&lt;/code&gt;&lt;a class="anchor" href="#safety-with-rm"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# NEVER do this with unquoted or unset variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;/&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# if DIR is empty → rm -rf / !!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Safe pattern&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; die &lt;span class="s2"&gt;&amp;#34;DIR is empty&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; die &lt;span class="s2"&gt;&amp;#34;Refusing to delete /&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="p"&gt;:?ERROR: DIR not set&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="find--the-swiss-army-knife"&gt;find — The Swiss Army Knife&lt;a class="anchor" href="#find--the-swiss-army-knife"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="basic-searches"&gt;Basic Searches&lt;a class="anchor" href="#basic-searches"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# By name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# exact glob match&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -iname &lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# case-insensitive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt; -o -name &lt;span class="s2"&gt;&amp;#34;*.js&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# OR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# By type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="c1"&gt;# regular files only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type d &lt;span class="c1"&gt;# directories only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type l &lt;span class="c1"&gt;# symlinks only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# By size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -size +100M &lt;span class="c1"&gt;# larger than 100MB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -size -1k &lt;span class="c1"&gt;# smaller than 1KB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# By time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -mtime -7 &lt;span class="c1"&gt;# modified in last 7 days&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -mtime +30 &lt;span class="c1"&gt;# modified more than 30 days ago&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -newer reference.txt &lt;span class="c1"&gt;# newer than reference file&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="actions"&gt;Actions&lt;a class="anchor" href="#actions"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Execute command on each result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.log&amp;#34;&lt;/span&gt; -exec rm &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt; -exec grep -l &lt;span class="s2"&gt;&amp;#34;TODO&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Batch execution (more efficient)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.log&amp;#34;&lt;/span&gt; -exec rm &lt;span class="o"&gt;{}&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Print with custom format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f -printf &lt;span class="s2"&gt;&amp;#34;%s %p\n&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# size and path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Delete directly (faster than -exec rm)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.tmp&amp;#34;&lt;/span&gt; -delete&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="combining-conditions"&gt;Combining Conditions&lt;a class="anchor" href="#combining-conditions"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# AND (implicit)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &lt;span class="s2"&gt;&amp;#34;*.log&amp;#34;&lt;/span&gt; -size +10M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# OR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . &lt;span class="se"&gt;\(&lt;/span&gt; -name &lt;span class="s2"&gt;&amp;#34;*.log&amp;#34;&lt;/span&gt; -o -name &lt;span class="s2"&gt;&amp;#34;*.tmp&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; -mtime +7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NOT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f ! -name &lt;span class="s2"&gt;&amp;#34;*.py&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Practical: find large old logs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find /var/log -name &lt;span class="s2"&gt;&amp;#34;*.log&amp;#34;&lt;/span&gt; -size +50M -mtime +30 -exec ls -lh &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="permissions"&gt;Permissions&lt;a class="anchor" href="#permissions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="understanding-permission-notation"&gt;Understanding Permission Notation&lt;a class="anchor" href="#understanding-permission-notation"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-rwxr-xr-- 1 alice developers 4096 Jan 1 12:00 script.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│├─┤├─┤├─┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ └── Others: read only (r--)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ └───── Group: read + execute (r-x)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───────── Owner: read + write + execute (rwx)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────── Type: - = file, d = directory, l = symlink&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="octal-numeric-permissions"&gt;Octal (Numeric) Permissions&lt;a class="anchor" href="#octal-numeric-permissions"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Octal&lt;/th&gt;
					&lt;th&gt;Binary&lt;/th&gt;
					&lt;th&gt;Permission&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;000&lt;/td&gt;
					&lt;td&gt;&amp;mdash; (none)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;001&lt;/td&gt;
					&lt;td&gt;&amp;ndash;x (execute)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;010&lt;/td&gt;
					&lt;td&gt;-w- (write)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;011&lt;/td&gt;
					&lt;td&gt;-wx (write + execute)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;100&lt;/td&gt;
					&lt;td&gt;r&amp;ndash; (read)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;101&lt;/td&gt;
					&lt;td&gt;r-x (read + execute)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;6&lt;/td&gt;
					&lt;td&gt;110&lt;/td&gt;
					&lt;td&gt;rw- (read + write)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;7&lt;/td&gt;
					&lt;td&gt;111&lt;/td&gt;
					&lt;td&gt;rwx (all)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="common-permission-patterns"&gt;Common Permission Patterns&lt;a class="anchor" href="#common-permission-patterns"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Octal&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
					&lt;th&gt;Use Case&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;755&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rwxr-xr-x&lt;/td&gt;
					&lt;td&gt;Executable scripts, directories&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;644&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rw-r&amp;ndash;r&amp;ndash;&lt;/td&gt;
					&lt;td&gt;Regular files&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;600&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rw&amp;mdash;&amp;mdash;-&lt;/td&gt;
					&lt;td&gt;Private files (keys, secrets)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;700&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rwx&amp;mdash;&amp;mdash;&lt;/td&gt;
					&lt;td&gt;Private directories&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;775&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rwxrwxr-x&lt;/td&gt;
					&lt;td&gt;Shared group directories&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;664&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;rw-rw-r&amp;ndash;&lt;/td&gt;
					&lt;td&gt;Shared group files&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="chmod--change-permissions"&gt;chmod — Change Permissions&lt;a class="anchor" href="#chmod--change-permissions"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Numeric&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;755&lt;/span&gt; script.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;644&lt;/span&gt; config.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; ~/.ssh/id_rsa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Symbolic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x script.sh &lt;span class="c1"&gt;# add execute for all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod u+w file.txt &lt;span class="c1"&gt;# add write for owner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod go-r file.txt &lt;span class="c1"&gt;# remove read for group and others&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod a+r file.txt &lt;span class="c1"&gt;# add read for all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rwx,go&lt;span class="o"&gt;=&lt;/span&gt;rx script.sh &lt;span class="c1"&gt;# set explicitly&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="chown--change-ownership"&gt;chown — Change Ownership&lt;a class="anchor" href="#chown--change-ownership"&gt;#&lt;/a&gt;&lt;/h3&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;chown alice file.txt &lt;span class="c1"&gt;# change owner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chown alice:developers file.txt &lt;span class="c1"&gt;# change owner and group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chown -R alice:developers dir/ &lt;span class="c1"&gt;# recursive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chown :developers file.txt &lt;span class="c1"&gt;# change group only&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="directory-permissions"&gt;Directory Permissions&lt;a class="anchor" href="#directory-permissions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Directories have different semantics for the same bits:&lt;/p&gt;</description></item><item><title>Regular Expressions</title><link>https://kyngo.github.io/learning-paths/paths/scripting/08-regular-expressions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/08-regular-expressions/</guid><description>&lt;h2 id="what-are-regular-expressions"&gt;What Are Regular Expressions?&lt;a class="anchor" href="#what-are-regular-expressions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Regular expressions (regex) are patterns that describe sets of strings. They&amp;rsquo;re a universal skill — the same concepts work in grep, sed, awk, Python, JavaScript, and every text editor.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 Pattern[&amp;#34;Pattern: ^[0-9]{4}-[0-9]{2}&amp;#34;] --&amp;gt; Engine[&amp;#34;Regex Engine&amp;#34;]
 Input[&amp;#34;Input: 2024-01-15 Error occurred&amp;#34;] --&amp;gt; Engine
 Engine --&amp;gt; Match[&amp;#34;Match: 2024-01&amp;#34;]&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="basic-syntax"&gt;Basic Syntax&lt;a class="anchor" href="#basic-syntax"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="literal-characters-and-metacharacters"&gt;Literal Characters and Metacharacters&lt;a class="anchor" href="#literal-characters-and-metacharacters"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Pattern&lt;/th&gt;
					&lt;th&gt;Matches&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;abc&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Literal &amp;ldquo;abc&amp;rdquo;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any single character (except newline)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;\&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Escape next character&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="anchors"&gt;Anchors&lt;a class="anchor" href="#anchors"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Pattern&lt;/th&gt;
					&lt;th&gt;Matches&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Start of line&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;End of line&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;\b&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Word boundary (Perl/PCRE)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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;grep &lt;span class="s2"&gt;&amp;#34;^ERROR&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# lines starting with ERROR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep &lt;span class="s2"&gt;&amp;#34;\.py&lt;/span&gt;$&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; filelist &lt;span class="c1"&gt;# lines ending with .py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -P &lt;span class="s2"&gt;&amp;#34;\berror\b&amp;#34;&lt;/span&gt; log &lt;span class="c1"&gt;# &amp;#34;error&amp;#34; as whole word&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="character-classes"&gt;Character Classes&lt;a class="anchor" href="#character-classes"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Pattern&lt;/th&gt;
					&lt;th&gt;Matches&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[abc]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any one of a, b, c&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[^abc]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any character NOT a, b, c&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[a-z]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any lowercase letter&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[A-Z]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any uppercase letter&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[0-9]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any digit&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[a-zA-Z0-9]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Any alphanumeric&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="posix-character-classes"&gt;POSIX Character Classes&lt;a class="anchor" href="#posix-character-classes"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Class&lt;/th&gt;
					&lt;th&gt;Equivalent&lt;/th&gt;
					&lt;th&gt;Matches&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:alpha:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[a-zA-Z]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Letters&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:digit:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[0-9]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Digits&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:alnum:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[a-zA-Z0-9]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Alphanumeric&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:space:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[ \t\n\r\f\v]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Whitespace&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:upper:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[A-Z]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Uppercase&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[:lower:]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;[a-z]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Lowercase&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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;grep &lt;span class="s2"&gt;&amp;#34;[[:digit:]]&amp;#34;&lt;/span&gt; file &lt;span class="c1"&gt;# lines with at least one digit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep &lt;span class="s2"&gt;&amp;#34;[[:space:]]&lt;/span&gt;$&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; file &lt;span class="c1"&gt;# lines with trailing whitespace&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="quantifiers"&gt;Quantifiers&lt;a class="anchor" href="#quantifiers"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Pattern&lt;/th&gt;
					&lt;th&gt;Matches&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Zero or more of preceding&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;One or more of preceding (ERE)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Zero or one of preceding (ERE)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;{n}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Exactly n times&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;{n,}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;n or more times&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;{n,m}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Between n and m times&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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;grep -E &lt;span class="s2"&gt;&amp;#34;a{3}&amp;#34;&lt;/span&gt; file &lt;span class="c1"&gt;# &amp;#34;aaa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -E &lt;span class="s2"&gt;&amp;#34;[0-9]{1,3}&amp;#34;&lt;/span&gt; file &lt;span class="c1"&gt;# 1-3 digit numbers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -E &lt;span class="s2"&gt;&amp;#34;https?&amp;#34;&lt;/span&gt; file &lt;span class="c1"&gt;# &amp;#34;http&amp;#34; or &amp;#34;https&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="grouping-and-alternation"&gt;Grouping and Alternation&lt;a class="anchor" href="#grouping-and-alternation"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Pattern&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;(abc)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Group (capture)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;a|b&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;a OR b (BRE)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;a|b&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;a OR b (ERE, literal pipe)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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;grep -E &lt;span class="s2"&gt;&amp;#34;(error|warning|critical)&amp;#34;&lt;/span&gt; log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -E &lt;span class="s2"&gt;&amp;#34;^(GET|POST|PUT|DELETE) &amp;#34;&lt;/span&gt; access.log&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="bre-vs-ere-vs-pcre"&gt;BRE vs ERE vs PCRE&lt;a class="anchor" href="#bre-vs-ere-vs-pcre"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th style="text-align: center"&gt;BRE (Basic)&lt;/th&gt;
					&lt;th style="text-align: center"&gt;ERE (Extended)&lt;/th&gt;
					&lt;th style="text-align: center"&gt;PCRE (Perl)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Default tool&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;grep -E&lt;/code&gt;, &lt;code&gt;awk&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;grep -P&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Must escape&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Literal&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Literal&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;\d&lt;/code&gt;, &lt;code&gt;\w&lt;/code&gt;, &lt;code&gt;\s&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Lookahead/behind&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Non-greedy &lt;code&gt;*?&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Backreferences&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;\1&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;\1&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;code&gt;\1&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Use ERE (&lt;code&gt;grep -E&lt;/code&gt;, &lt;code&gt;sed -E&lt;/code&gt;) for most tasks. Use PCRE (&lt;code&gt;grep -P&lt;/code&gt;) when you need &lt;code&gt;\d&lt;/code&gt;, &lt;code&gt;\w&lt;/code&gt;, or lookaheads.&lt;/p&gt;</description></item><item><title>Process Management</title><link>https://kyngo.github.io/learning-paths/paths/scripting/09-process-management/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/09-process-management/</guid><description>&lt;h2 id="what-is-a-process"&gt;What is a Process?&lt;a class="anchor" href="#what-is-a-process"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A process is a running instance of a program. Every command you run creates a process with its own PID (Process ID), memory space, and file descriptors.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Init[&amp;#34;init/systemd (PID 1)&amp;#34;]
 Init --&amp;gt; Shell[&amp;#34;bash (PID 1234)&amp;#34;]
 Shell --&amp;gt; Script[&amp;#34;./deploy.sh (PID 5678)&amp;#34;]
 Script --&amp;gt; Curl[&amp;#34;curl (PID 5679)&amp;#34;]
 Script --&amp;gt; Grep[&amp;#34;grep (PID 5680)&amp;#34;]&lt;/pre&gt;&lt;h3 id="process-states"&gt;Process States&lt;a class="anchor" href="#process-states"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;State&lt;/th&gt;
					&lt;th&gt;Meaning&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Running (R)&lt;/td&gt;
					&lt;td&gt;Actively executing on CPU&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Sleeping (S)&lt;/td&gt;
					&lt;td&gt;Waiting for I/O or event&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Stopped (T)&lt;/td&gt;
					&lt;td&gt;Suspended (Ctrl+Z)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Zombie (Z)&lt;/td&gt;
					&lt;td&gt;Finished but parent hasn&amp;rsquo;t collected exit status&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="viewing-processes"&gt;Viewing Processes&lt;a class="anchor" href="#viewing-processes"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="c1"&gt;# Current user&amp;#39;s processes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps aux &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;[m]yapp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# All processes, full format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps -ef
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Process tree&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pstree -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Find PID by name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pgrep -f &lt;span class="s2"&gt;&amp;#34;python app.py&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pidof nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Real-time monitoring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;top &lt;span class="c1"&gt;# built-in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;htop &lt;span class="c1"&gt;# better (if installed)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="useful-ps-patterns"&gt;Useful &lt;code&gt;ps&lt;/code&gt; Patterns&lt;a class="anchor" href="#useful-ps-patterns"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Top CPU consumers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps aux --sort&lt;span class="o"&gt;=&lt;/span&gt;-%cpu &lt;span class="p"&gt;|&lt;/span&gt; head -10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Top memory consumers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps aux --sort&lt;span class="o"&gt;=&lt;/span&gt;-%mem &lt;span class="p"&gt;|&lt;/span&gt; head -10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Processes by a specific user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps -u alice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Show process hierarchy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps -ejH&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="background-jobs"&gt;Background Jobs&lt;a class="anchor" href="#background-jobs"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="c1"&gt;# Run in background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;long_command &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PID: &lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# PID of last background process&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List background jobs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;jobs&lt;/span&gt; &lt;span class="c1"&gt;# shows job numbers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;jobs&lt;/span&gt; -l &lt;span class="c1"&gt;# includes PIDs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Bring to foreground&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;fg&lt;/span&gt; %1 &lt;span class="c1"&gt;# job number 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Suspend and background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Press Ctrl+Z (suspends foreground process)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;bg&lt;/span&gt; %1 &lt;span class="c1"&gt;# resume in background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Detach from terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nohup long_command &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="c1"&gt;# survives terminal close&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;disown&lt;/span&gt; %1 &lt;span class="c1"&gt;# detach already-running job&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="wait-for-background-processes"&gt;Wait for Background Processes&lt;a class="anchor" href="#wait-for-background-processes"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Wait for specific PID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;long_task_1 &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;pid1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;long_task_2 &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;pid2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nv"&gt;$pid1&lt;/span&gt; &lt;span class="nv"&gt;$pid2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Both tasks complete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Wait for all background jobs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wait&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="signals"&gt;Signals&lt;a class="anchor" href="#signals"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Signals are software interrupts sent to processes:&lt;/p&gt;</description></item><item><title>Script Debugging and Error Handling</title><link>https://kyngo.github.io/learning-paths/paths/scripting/10-debugging-error-handling/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/10-debugging-error-handling/</guid><description>&lt;h2 id="the-problem-silent-failures"&gt;The Problem: Silent Failures&lt;a class="anchor" href="#the-problem-silent-failures"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Without explicit error handling, shell scripts fail silently and continue executing — often causing more damage than the original error:&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;&lt;span class="c1"&gt;# Dangerous: if cd fails, rm deletes from WRONG directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /data/temp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf *
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Safe: exit if cd fails&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /data/temp &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf *&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="strict-mode-set--euo-pipefail"&gt;Strict Mode: &lt;code&gt;set -euo pipefail&lt;/code&gt;&lt;a class="anchor" href="#strict-mode-set--euo-pipefail"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The single most important line in any bash script:&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;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -euo pipefail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="what-each-flag-does"&gt;What Each Flag Does&lt;a class="anchor" href="#what-each-flag-does"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Flag&lt;/th&gt;
					&lt;th&gt;Without It&lt;/th&gt;
					&lt;th&gt;With It&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;-e&lt;/code&gt; (errexit)&lt;/td&gt;
					&lt;td&gt;Script continues after failed commands&lt;/td&gt;
					&lt;td&gt;Script exits immediately on failure&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;-u&lt;/code&gt; (nounset)&lt;/td&gt;
					&lt;td&gt;Unset variables expand to empty string&lt;/td&gt;
					&lt;td&gt;Unset variables cause an error&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;-o pipefail&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Pipe exit code = last command&amp;rsquo;s code&lt;/td&gt;
					&lt;td&gt;Pipe exit code = first failure&amp;rsquo;s code&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="-e-in-detail"&gt;&lt;code&gt;-e&lt;/code&gt; in Detail&lt;a class="anchor" href="#-e-in-detail"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="nb"&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp important.dat /backup/ &lt;span class="c1"&gt;# if this fails...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm important.dat &lt;span class="c1"&gt;# ...this NEVER runs (script exits)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Done&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# also never runs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Commands that legitimately return non-zero need special handling:&lt;/p&gt;</description></item><item><title>Cron, Systemd Timers, and Automation</title><link>https://kyngo.github.io/learning-paths/paths/scripting/11-cron-automation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/11-cron-automation/</guid><description>&lt;h2 id="scheduled-task-execution"&gt;Scheduled Task Execution&lt;a class="anchor" href="#scheduled-task-execution"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Automation means running scripts without human intervention — on a schedule, in response to events, or as part of a pipeline.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Trigger[&amp;#34;Trigger&amp;#34;]
 Trigger --&amp;gt; Cron[&amp;#34;Cron (time-based)&amp;#34;]
 Trigger --&amp;gt; Systemd[&amp;#34;Systemd Timer (time-based, managed)&amp;#34;]
 Trigger --&amp;gt; Event[&amp;#34;Event (file change, webhook)&amp;#34;]
 Trigger --&amp;gt; CI[&amp;#34;CI/CD Pipeline (code push)&amp;#34;]
 
 Cron --&amp;gt; Script[&amp;#34;Script Execution&amp;#34;]
 Systemd --&amp;gt; Script
 Event --&amp;gt; Script
 CI --&amp;gt; Script&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="cron"&gt;Cron&lt;a class="anchor" href="#cron"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The traditional Unix scheduler. Runs commands at specified times.&lt;/p&gt;</description></item><item><title>Portable Scripting and POSIX Compliance</title><link>https://kyngo.github.io/learning-paths/paths/scripting/12-portable-scripting-posix/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/scripting/12-portable-scripting-posix/</guid><description>&lt;h2 id="why-portability-matters"&gt;Why Portability Matters&lt;a class="anchor" href="#why-portability-matters"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not every system has bash. Alpine Docker images use &lt;code&gt;ash&lt;/code&gt;, BSD systems use &lt;code&gt;sh&lt;/code&gt;, embedded systems have minimal shells. If your script must run across different environments, you need POSIX compliance.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Script[&amp;#34;Your Script&amp;#34;]
 Script --&amp;gt; Q{&amp;#34;Where does it run?&amp;#34;}
 Q --&amp;gt;|&amp;#34;Linux servers (bash guaranteed)&amp;#34;| Bash[&amp;#34;Use #!/bin/bash&amp;#34;]
 Q --&amp;gt;|&amp;#34;Docker (Alpine, minimal)&amp;#34;| POSIX[&amp;#34;Use #!/bin/sh&amp;#34;]
 Q --&amp;gt;|&amp;#34;macOS + Linux&amp;#34;| Env[&amp;#34;Use #!/usr/bin/env bash&amp;#34;]
 Q --&amp;gt;|&amp;#34;CI/CD (controlled)&amp;#34;| Bash
 Q --&amp;gt;|&amp;#34;Multi-OS distribution&amp;#34;| POSIX&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="posix-vs-bash-features"&gt;POSIX vs Bash Features&lt;a class="anchor" href="#posix-vs-bash-features"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th style="text-align: center"&gt;POSIX (&lt;code&gt;sh&lt;/code&gt;)&lt;/th&gt;
					&lt;th style="text-align: center"&gt;Bash&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;[[ ]]&lt;/code&gt; extended test&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Arrays&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;local&lt;/code&gt; keyword&lt;/td&gt;
					&lt;td style="text-align: center"&gt;Not guaranteed&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$(( ))&lt;/code&gt; arithmetic&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$(command)&lt;/code&gt; substitution&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;{1..10}&lt;/code&gt; brace expansion&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; here string&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Process substitution &lt;code&gt;&amp;lt;()&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;=~&lt;/code&gt; regex matching&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;==&lt;/code&gt; in &lt;code&gt;[[ ]]&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;source&lt;/code&gt; keyword&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌ (use &lt;code&gt;.&lt;/code&gt;)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;function&lt;/code&gt; keyword&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;${var,,}&lt;/code&gt; case change&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅ (bash 4+)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;set -o pipefail&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;$RANDOM&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;read -p&lt;/code&gt; (prompt)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="writing-posix-compliant-scripts"&gt;Writing POSIX-Compliant Scripts&lt;a class="anchor" href="#writing-posix-compliant-scripts"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="test-commands"&gt;Test Commands&lt;a class="anchor" href="#test-commands"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash (not portable)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;+$ &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX equivalent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# No regex — use case or grep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;starts with digit&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;esac&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="string-operations"&gt;String Operations&lt;a class="anchor" href="#string-operations"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# single = for equality&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="functions"&gt;Functions&lt;a class="anchor" href="#functions"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; greet &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;greet&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# no guaranteed &amp;#39;local&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="loops-without-brace-expansion"&gt;Loops Without Brace Expansion&lt;a class="anchor" href="#loops-without-brace-expansion"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="o"&gt;{&lt;/span&gt;1..10&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -le &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="no-arrays--alternatives"&gt;No Arrays — Alternatives&lt;a class="anchor" href="#no-arrays--alternatives"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash arrays&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;one.txt&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;two.txt&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;three.txt&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; f in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX — use positional parameters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -- &lt;span class="s2"&gt;&amp;#34;one.txt&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;two.txt&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;three.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; f in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX — use newline-separated string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;one.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;two.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;three.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r f&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="no-process-substitution"&gt;No Process Substitution&lt;a class="anchor" href="#no-process-substitution"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;diff &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;sort file1&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;sort file2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX — use temp files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort file1 &amp;gt; /tmp/sorted1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sort file2 &amp;gt; /tmp/sorted2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;diff /tmp/sorted1 /tmp/sorted2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm /tmp/sorted1 /tmp/sorted2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="no-pipefail"&gt;No Pipefail&lt;a class="anchor" href="#no-pipefail"&gt;#&lt;/a&gt;&lt;/h3&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;&lt;span class="c1"&gt;# Bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd1 &lt;span class="p"&gt;|&lt;/span&gt; cmd2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX — check PIPESTATUS manually (not available)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alternative: use intermediate files or check each command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd1 &amp;gt; /tmp/intermediate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd2 &amp;lt; /tmp/intermediate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="when-to-use-posix"&gt;When to Use POSIX&lt;a class="anchor" href="#when-to-use-posix"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Scenario&lt;/th&gt;
					&lt;th style="text-align: center"&gt;Use POSIX&lt;/th&gt;
					&lt;th style="text-align: center"&gt;Use Bash&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Docker (Alpine, scratch)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;System init scripts&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Embedded/IoT&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cross-platform distribution&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Linux servers (you control)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CI/CD pipelines&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Developer tooling&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Complex scripts (arrays, regex)&lt;/td&gt;
					&lt;td style="text-align: center"&gt;❌&lt;/td&gt;
					&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="portability-checklist"&gt;Portability Checklist&lt;a class="anchor" href="#portability-checklist"&gt;#&lt;/a&gt;&lt;/h2&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;&lt;span class="cp"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# POSIX-compliant script checklist:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ Shebang: #!/bin/sh (not #!/bin/bash)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ Tests: [ ] not [[ ]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ Equality: = not ==&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No arrays&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No local (or accept it&amp;#39;s not guaranteed)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No brace expansion {1..10}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No here strings &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No process substitution &amp;lt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No pipefail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No source (use . instead)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No function keyword (use name() { })&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ No [[ =~ ]] regex&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ printf over echo (echo behavior varies!)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="the-echo-problem"&gt;The &lt;code&gt;echo&lt;/code&gt; Problem&lt;a class="anchor" href="#the-echo-problem"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;echo&lt;/code&gt; behavior varies across systems:&lt;/p&gt;</description></item></channel></rss>