<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>BASH on Ricky</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/tags/bash/</link><description>Recent content in BASH on Ricky</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Mon, 20 Jul 2026 09:19:00 +0800</lastBuildDate><atom:link href="https://59d713fc.rickylin.pages.dev/zh-tw/tags/bash/index.xml" rel="self" type="application/rss+xml"/><item><title>Articles</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2026/20260720-articles/</link><pubDate>Mon, 20 Jul 2026 09:19:00 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2026/20260720-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.submission.directory/" target="_blank" rel="noopener">A website submission directory to submit your business, startup, or website&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.cloudflare.com/drop/" target="_blank" rel="noopener">Summon your site - HTML, CSS, JS. See it live instantly.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://metawilo.com/" target="_blank" rel="noopener">台灣罪犯圖鑑&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://clocks.dev/" target="_blank" rel="noopener">Collection of digital clock designs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://clig.dev/" target="_blank" rel="noopener">Command Line Interface Guidelines&lt;/a>&lt;/li>
&lt;li>&lt;strong>Github&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/searxng/searxng" target="_blank" rel="noopener">SearXNG is a free internet metasearch engine which aggregates results from various search services and databases. Users are neither tracked nor profiled.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/HelixDB/helix-db" target="_blank" rel="noopener">HelixDB is an OLTP graph-vector database built in Rust on Object Storage.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/VSCodium/vscodium" target="_blank" rel="noopener">vscodium: binary releases of VS Code without MS branding/telemetry/licensing&lt;/a> - &lt;code>VSCodium&lt;/code> 使用 &lt;code>Open VSX Registry&lt;/code> 替換 &lt;code>Visual Studio Marketplace&lt;/code>，相容大多數 extension。&lt;/li>
&lt;li>&lt;a href="https://github.com/EpicGames/lore" target="_blank" rel="noopener">Lore is a next-generation, open source version control system&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/paytonjjones/bsharp" target="_blank" rel="noopener">bsharp: A tool to teach children perfect pitch&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/stamparm/maltrail" target="_blank" rel="noopener">maltrail: Malicious traffic detection system&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/schollz/croc" target="_blank" rel="noopener">croc: Easily and securely send things from one computer to another&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/StarTrail-org/PixelRAG" target="_blank" rel="noopener">PixelRAG: The end of web parsing. The beginning of scalable pixel-native search. link: https://pixelrag.ai/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/azukaar/Cosmos-Server" target="_blank" rel="noopener">Cosmos is the most secure and easy way to self-host a Home Server. It acts as a secure gateway to your application, as well as a server manager. It aims to solve the increasingly worrying problem of vulnerable self-hosted applications and personal servers.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/jhaals/yopass" target="_blank" rel="noopener">yopass: Secure sharing of secrets, passwords and files&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/OpenHub-Store/GitHub-Store" target="_blank" rel="noopener">GitHub-Store: A free, open-source app store for developers&amp;rsquo; releases on GitHub, Codeberg &amp;amp; Forgejo — browse, discover, and install apps with one click.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/n0-computer/iroh" target="_blank" rel="noopener">iroh: IP addresses break, dial keys instead. A library that adds QUIC + NAT Traversal to your apps.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Crosstalk-Solutions/project-nomad" target="_blank" rel="noopener">Project N.O.M.A.D, is a self-contained, offline survival computer packed with critical tools, knowledge, and AI to keep you informed and empowered—anytime, anywhere.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/sw33tLie/macshot" target="_blank" rel="noopener">macshot: Feature-packed native macOS screenshot &amp;amp; recording tool: annotate, auto-redact PII, record GIFs, OCR + translate, scroll capture, beautify, and more. No Electron, no subscription.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/iOfficeAI/OfficeCLI" target="_blank" rel="noopener">OfficeCLI is the first and best Office suite purpose-built for AI agents to read, edit, and automate Word, Excel, and PowerPoint files. Free, open-source, single binary, no Office installation required.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Diolinux/Photogimp" target="_blank" rel="noopener">A Patch for GIMP 3+(https://www.gimp.org/) for Photoshop Users&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/chattocorp/chatto" target="_blank" rel="noopener">chatto: A fully-featured team and group chat application that you can easily selfhost.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/nextest-rs/nextest" target="_blank" rel="noopener">nextest: A next-generation test runner for Rust.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/peetzweg/opendisplay" target="_blank" rel="noopener">OpenDisplay：Sidecar 与 Duet Display 的开源替代品，把闲置的 iPhone / iPad 变成 Mac 第二显示屏&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/pavlobu/deskreen" target="_blank" rel="noopener">Deskreen：将局域网设备变为电脑的第二块屏幕&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Skill&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/DietrichGebert/ponytail" target="_blank" rel="noopener">ponytail: Makes your AI agent think like the laziest senior dev in the room. The best code is the code you never wrote.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/nvidia/skillspector" target="_blank" rel="noopener">skillspector: Security scanner for AI agent skills. Detect vulnerabilities, malicious patterns, and security risks.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/cloudflare/security-audit-skill" target="_blank" rel="noopener">security-audit: A coding-agent skill for multi-phase security audits with independently verified, machine-readable findings&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Article&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://www.rfc-editor.org/info/rfc10008/" target="_blank" rel="noopener">RFC 10008: The HTTP QUERY Method&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://mareksuppa.com/til/bash-dev-tcp-http-without-curl/" target="_blank" rel="noopener">Making HTTP requests from a container that has no curl, using bash &lt;code>/dev/tcp&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://t.me/TheB1ackParade/1076" target="_blank" rel="noopener">rr-debugger(https://github.com/rr-debugger/rr)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.deno.com/runtime/desktop/" target="_blank" rel="noopener">Deno Desktop&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.fosslinux.com/158206/linux-on-older-hardware-revival-guide.htm" target="_blank" rel="noopener">Linux on Older Hardware: The Complete Revival Guide (2026)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://news.ycombinator.com/item?id=48842459" target="_blank" rel="noopener">Show HN: Getting GLM 5.2 running on my slow computer&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://mrmad.com.tw/how-to-turn-on-iphone-guided-access" target="_blank" rel="noopener">iPhone引導模式怎麼開？借手機人不怕隱私外洩和一鍵鎖定App&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ikrima.dev/dev-notes/linux/linux-modern-tools/" target="_blank" rel="noopener">Modern Linux Tools&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="iphone引導模式怎麼開借手機人不怕隱私外洩和一鍵鎖定app">iPhone引導模式怎麼開？借手機人不怕隱私外洩和一鍵鎖定App&lt;/h2>
&lt;h3 id="開啟與設定功能">開啟與設定功能&lt;/h3>
&lt;ol>
&lt;li>打開 iPhone 上的 &lt;strong>「設定」&lt;/strong> App。&lt;/li>
&lt;li>點選 &lt;strong>「輔助使用」&lt;/strong>。&lt;/li>
&lt;li>往下找到並點選 &lt;strong>「引導使用模式」&lt;/strong>，然後將其&lt;strong>開啟&lt;/strong>。&lt;/li>
&lt;li>建議順便進行以下設定：&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>&lt;strong>密碼設定&lt;/strong>：點一下「密碼設定」&amp;gt;「設定引導使用模式密碼」，輸入一組解鎖密碼，並可同時開啟 &lt;strong>Face ID&lt;/strong> 或 &lt;strong>Touch ID&lt;/strong> 作為快速解鎖/結束的方式。&lt;/li>
&lt;li>&lt;strong>輔助使用快速鍵&lt;/strong>：建議將其開啟，之後只要連按三下側邊按鈕就能快速叫出或退出此模式。&lt;/li>
&lt;/ul>
&lt;h3 id="開始使用將-iphone-鎖定在單一-app">開始使用（將 iPhone 鎖定在單一 App）&lt;/h3>
&lt;ol>
&lt;li>打開你想要讓別人（或自己專注）使用的 &lt;strong>App&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>啟動引導使用模式&lt;/strong>：&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>&lt;strong>具備 Face ID 的 iPhone&lt;/strong>（全螢幕機型）：&lt;strong>連按三下側邊按鈕&lt;/strong>（電源鍵）。&lt;/li>
&lt;li>&lt;strong>具備主畫面按鈕的舊款 iPhone&lt;/strong>：&lt;strong>連按三下主畫面按鈕&lt;/strong>（Home 鍵）。&lt;/li>
&lt;li>或者也可以呼叫 Siri：「打開引導使用模式」。&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>如果跳出輔助使用快速鍵面板，請點選 &lt;strong>「引導使用模式」&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>自訂限制區域（選用）&lt;/strong>：&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>如果想讓螢幕上的特定區域&lt;strong>無法被觸控點擊&lt;/strong>（例如遊戲內的廣告區塊），直接用手指在該區域&lt;strong>畫一個圓圈&lt;/strong>，之後可以拖曳邊框來調整大小。&lt;/li>
&lt;/ul>
&lt;ol start="5">
&lt;li>&lt;strong>點一下右下角的「階段設定」&lt;/strong>（或選項），可以自由決定是否停用以下功能：&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>側邊按鈕 / 頂端按鈕&lt;/li>
&lt;li>音量按鈕&lt;/li>
&lt;li>動作（防止螢幕自動旋轉或因晃動而有反應）&lt;/li>
&lt;li>軟體鍵盤&lt;/li>
&lt;li>觸控（若想完全讓整個螢幕無法觸控可關閉此項）&lt;/li>
&lt;li>時間限制&lt;/li>
&lt;/ul>
&lt;ol start="6">
&lt;li>設定完成後，點一下右上角的 &lt;strong>「完成」&lt;/strong>，再點一下 &lt;strong>「開始」&lt;/strong> 即可正式鎖定。&lt;/li>
&lt;/ol>
&lt;h3 id="如何結束引導使用模式">如何結束引導使用模式&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>連按三下&lt;/strong>側邊按鈕（或主畫面按鈕）。&lt;/li>
&lt;li>輸入你剛剛設定的&lt;strong>引導使用模式密碼&lt;/strong>（或直接使用 Face ID / Touch ID 驗證）。&lt;/li>
&lt;li>畫面左上角會出現 &lt;strong>「結束」&lt;/strong> 按鈕，點下去即可退出此模式。&lt;/li>
&lt;/ol></description></item><item><title>TIL：Bash 腳本的 timeout</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</link><pubDate>Thu, 12 Jun 2025 09:04:00 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://heitorpb.github.io/bla/timeout/" target="_blank" rel="noopener">TIL：Bash 腳本的 timeout&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>timeout 1m ./until.sh&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>包一層&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>timeout 1m bash -c &lt;span style="color:#e6db74">&amp;#34;until curl --silent --fail-with-body 10.0.0.1:8080/health; do
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> sleep 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">done&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>進階 Shell 腳本技巧：用 Bash 自動化複雜任務</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2024/20240925-advanced-shell-scripting/</link><pubDate>Wed, 25 Sep 2024 09:23:00 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2024/20240925-advanced-shell-scripting/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://omid.dev/2024/06/19/advanced-shell-scripting-techniques-automating-complex-tasks-with-bash/" target="_blank" rel="noopener">進階 Shell 腳本技巧：用 Bash 自動化複雜任務&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="使用內建指令">使用內建指令&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>內建指令執行更快，因為不需要載入外部程序。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="減少子殼層">減少子殼層&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>子殼層會帶來效能成本。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>output&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cat file.txt&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>output&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;file.txt&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="使用陣列處理大量資料">使用陣列處理大量資料&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>處理大量資料時，陣列比多個變數更有效率，也更好管理。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item1&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;apple&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item2&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;banana&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item3&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;cherry&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>items&lt;span style="color:#f92672">=(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;apple&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;banana&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;cherry&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> item in &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>items[@]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$item&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="啟用-noclobber">啟用 Noclobber&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>避免檔案被意外覆寫。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>set -o noclobber
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="使用函式">使用函式&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>函式可以封裝並重用程式碼，讓腳本更乾淨、重複更少。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="高效的檔案操作">高效的檔案操作&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>進行檔案操作時，使用更有效率的技巧以降低資源消耗。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> read -r line; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$line&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span> &amp;lt; file.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> IFS&lt;span style="color:#f92672">=&lt;/span> read -r line; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$line&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span> &amp;lt; file.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="平行處理">平行處理&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>像 &lt;code>xargs&lt;/code> 和 GNU &lt;code>parallel&lt;/code> 這類工具非常實用。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="錯誤處理">錯誤處理&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>健全的錯誤處理對建立可靠、易維護的腳本至關重要。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Exit on Error: Using set -e ensures that your script exits immediately if any command fails, preventing cascading errors.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Custom Error Messages: Implement custom error messages to provide more context when something goes wrong.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>command1 &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#f92672">{&lt;/span> echo &lt;span style="color:#e6db74">&amp;#34;command1 failed&amp;#34;&lt;/span>; exit 1; &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Trap Signals: Use the `trap` command to catch and handle signals and errors gracefully.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trap &lt;span style="color:#e6db74">&amp;#39;echo &amp;#34;Error occurred&amp;#34;; cleanup; exit 1&amp;#39;&lt;/span> ERR
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">function&lt;/span> cleanup&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Cleanup code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Validate Inputs: Always validate user inputs and script arguments to prevent unexpected behavior.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> -z &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>$0&lt;span style="color:#e6db74"> &amp;lt;argument&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Logging: Implement logging to keep track of script execution and diagnose issues.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>logfile&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;script.log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exec &amp;gt; &amp;gt;&lt;span style="color:#f92672">(&lt;/span>tee -i $logfile&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exec 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Script started&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="自動化複雜的系統管理工作">自動化複雜的系統管理工作&lt;/h4>
&lt;ol>
&lt;li>自動化備份&lt;/li>
&lt;li>系統監控&lt;/li>
&lt;li>使用者管理&lt;/li>
&lt;li>自動更新&lt;/li>
&lt;li>網路設定&lt;/li>
&lt;/ol></description></item><item><title>寫 Web 也可以用 Makefile：好好管理你的環境流程</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2024/20240805-use-makefile-to-manage-workflows-for-web-projects/</link><pubDate>Mon, 05 Aug 2024 17:21:24 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2024/20240805-use-makefile-to-manage-workflows-for-web-projects/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.goodjack.tw/2023/01/use-makefile-to-manage-workflows-for-web-projects.html" target="_blank" rel="noopener">寫 Web 也可以用 Makefile：好好管理你的環境流程&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://gagor.pro/2024/02/how-i-stopped-worrying-and-loved-makefiles/" target="_blank" rel="noopener">How I stopped worrying and loved Makefiles&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>注意：Makefile 的縮排應使用 Tab，否則會出現語法問題。&lt;/strong>&lt;/p>
&lt;h2 id="makefile-的主要本體target">Makefile 的主要本體：Target&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">up&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cp .env.example .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose up -d workspace
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">stop&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose stop
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">zsh&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose exec workspace zsh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>本例有三個 Target：&lt;code>up&lt;/code>、&lt;code>stop&lt;/code>、&lt;code>zsh&lt;/code>。Makefile 預設將第一個 Target 視為 &lt;a href="https://www.gnu.org/software/make/manual/html_node/Goals.html" target="_blank" rel="noopener">Goal&lt;/a>(不能是點（dot）開頭的 Target)，是專案的最主要流程，可以直接用 &lt;code>make&lt;/code> 執行。以本例來說，執行 &lt;code>make&lt;/code> 和 &lt;code>make up&lt;/code> 是一樣的結果。&lt;/li>
&lt;li>但其實剛剛複製檔案的例子不是常見的 Make 用法。Make 的強項是在自動判斷有沒有必要執行每個 Target 的流程。例如我們常常將機敏資料放在 .env 中，若 .env 已經存在，就不應該再複製 .env.example 覆寫過去了。這時候我們可以把 .env 做成一個 Target：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">up&lt;/span>&lt;span style="color:#f92672">:&lt;/span> .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose up -d workspace
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">.env&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cp .env.example .env
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>Target 名稱預設是被視為檔名的。Make 之所以稱為 make，就是想要「製作」出指定的 Target，當符合指定條件時（如檔案不存在）才會執行 Target 的內容。
&lt;ul>
&lt;li>以本例來說，我們執行 &lt;code>up&lt;/code> Target 時，如果 .env 不存在，就會先執行 &lt;code>.env&lt;/code> Target 以複製出 .env，接著才會啟動 workspace container。如果執行 &lt;code>up&lt;/code> Target 時 .env 已經存在，就會略過 &lt;code>.env&lt;/code> Target，直接啟動 workspace container。&lt;/li>
&lt;li>同樣地，如果我們目錄中有「up」這個檔案， &lt;code>up&lt;/code> Target 就不會被執行了。這時我們可以設定 &lt;a href="https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html" target="_blank" rel="noopener">Phony Target&lt;/a>，告訴 Make 哪些 Target 不是檔案的名稱，而是單純流程的命名。寫法如下：&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">.PHONY&lt;/span>&lt;span style="color:#f92672">:&lt;/span> up stop zsh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="來點變數">來點變數&lt;/h2>
&lt;p>Make 當然也支援變數（&lt;a href="https://www.gnu.org/software/make/manual/html_node/Setting.html" target="_blank" rel="noopener">Variable&lt;/a>），與常見的 Unix 環境變數慣例相同，我們習慣用 SCREAMING_SNAKE_CASE 表示法（全大寫和底線的表示法）。並且在使用時以 &lt;code>$()&lt;/code> 包裹變數名稱。&lt;/p></description></item><item><title>Bash 位元運算子</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2022/20220704-bash-bitwise-operators/</link><pubDate>Mon, 04 Jul 2022 15:20:39 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2022/20220704-bash-bitwise-operators/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/bash-bitwise-operators" target="_blank" rel="noopener">Bash 位元運算子&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="bash-的進位轉換工具">Bash 的進位轉換工具&lt;/h3>
&lt;ul>
&lt;li>Bash 的算術展開允許我們用「進位數字 + #」的方式表示任意進位的數字。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ echo &lt;span style="color:#66d9ef">$((&lt;/span>&lt;span style="color:#ae81ff">2#1001&lt;/span>&lt;span style="color:#66d9ef">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">9&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>bc 可以用 ibase（輸入進位）與 obase（輸出進位）輕鬆進行進位轉換。以下將十進位的 9 轉成二進位。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ echo &lt;span style="color:#e6db74">&amp;#34;ibase=10;obase=2;9&amp;#34;&lt;/span> | bc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">1001&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>在 Bash 中解析命令列參數</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2022/20220607-bash-parse-command-line-arguments/</link><pubDate>Tue, 07 Jun 2022 14:48:47 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2022/20220607-bash-parse-command-line-arguments/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/bash-parse-command-line-arguments" target="_blank" rel="noopener">在 Bash 中解析命令列參數&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="getopts">getopts&lt;/h3>
&lt;blockquote>
&lt;p>&lt;code>getopts optstring opt [arg ...]&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> getopts &lt;span style="color:#e6db74">&amp;#39;abc:h&amp;#39;&lt;/span> opt; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$opt&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> a&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;a&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> b&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;b&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> c&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> arg&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$OPTARG&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;c&amp;#39; with &amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>OPTARG&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39; argument&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ?|h&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>shift &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$((&lt;/span> $OPTIND &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">))&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>optstring 代表支援的選項。若某個選項需要參數，則在它後面加冒號 (:)。例如選項 c 需要參數，會寫成 c:&lt;/li>
&lt;li>當選項有關聯參數時，getopts 會將參數字串存到 OPTARG shell 變數中。例如 option c 的參數會存到 OPTARG。&lt;/li>
&lt;li>opt 包含已解析的選項。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> getopts &lt;span style="color:#e6db74">&amp;#39;:abc:h&amp;#39;&lt;/span> opt; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$opt&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> a&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;a&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> b&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;b&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> c&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> arg&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$OPTARG&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;c&amp;#39; with &amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>OPTARG&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39; argument&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> h&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> :&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo -e &lt;span style="color:#e6db74">&amp;#34;option requires an argument.\nUsage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ?&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo -e &lt;span style="color:#e6db74">&amp;#34;Invalid command option.\nUsage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>shift &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$((&lt;/span> $OPTIND &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">))&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>注意我們也更新了 optstring，現在以冒號 (:) 開頭，會抑制預設的錯誤訊息。&lt;/li>
&lt;li>當 OPTERR 變數設為 0 時，getopts 會停用錯誤訊息輸出。&lt;/li>
&lt;/ul>
&lt;h3 id="使用-getopt-解析長選項">使用 getopt 解析長選項&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VALID_ARGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>getopt -o abg:d: --long alpha,beta,gamma:,delta: -- &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$@&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> $? -ne &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit 1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>eval set -- &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$VALID_ARGS&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> &lt;span style="color:#f92672">[&lt;/span> : &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -a | --alpha&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;alpha&amp;#39; option&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -b | --beta&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;beta&amp;#39; option&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -g | --gamma&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;gamma&amp;#39; option. Input argument is &amp;#39;&lt;/span>$2&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -d | --delta&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;delta&amp;#39; option. Input argument is &amp;#39;&lt;/span>$2&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --&lt;span style="color:#f92672">)&lt;/span> shift;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> break
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-o&lt;/code> 選項代表短選項&lt;/li>
&lt;li>&lt;code>--long&lt;/code> 選項代表長選項&lt;/li>
&lt;/ul></description></item><item><title>撰寫 Bash 腳本的最佳實務</title><link>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2021/20211206-bash-best-practices/</link><pubDate>Mon, 06 Dec 2021 11:11:54 +0800</pubDate><guid>https://59d713fc.rickylin.pages.dev/zh-tw/posts/2021/20211206-bash-best-practices/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://kvz.io/bash-best-practices.html" target="_blank" rel="noopener">撰寫 Bash 腳本的最佳實務&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.javacodegeeks.com/2013/10/shell-scripting-best-practices.html" target="_blank" rel="noopener">Shell 腳本撰寫最佳實務&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e"># Bash3 Boilerplate. Copyright (c) 2014, kvz.io&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o errexit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o pipefail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o nounset
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># set -o xtrace&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Set magic variables for current file &amp;amp; dir&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__dir&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>dirname &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BASH_SOURCE[0]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> pwd&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>__dir&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BASH_SOURCE[0]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__base&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename &lt;span style="color:#e6db74">${&lt;/span>__file&lt;span style="color:#e6db74">}&lt;/span> .sh&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__root&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>dirname &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>__dir&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> pwd&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#75715e"># &amp;lt;-- change this as it depends on your app&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>arg1&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1&lt;span style="color:#66d9ef">:-&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-shift-讀取函式參數">使用 shift 讀取函式參數&lt;/h5>
&lt;blockquote>
&lt;p>這樣在日後需要調整參數順序時會更容易。&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Processes a file.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># $1 - the name of the input file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># $2 - the name of the output file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>process_file&lt;span style="color:#f92672">(){&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> local -r input_file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> local -r output_file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="宣告你的變數">宣告你的變數&lt;/h5>
&lt;blockquote>
&lt;p>若可攜性是重點，請用 &lt;code>typeset&lt;/code> 取代 &lt;code>declare&lt;/code>。&lt;/p></description></item></channel></rss>