<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux on Wayne's blog | 偉恩的部落格 | 技術博客</title><link>https://blog.wayne-project.com/tags/linux/</link><description>Recent content in Linux on Wayne's blog | 偉恩的部落格 | 技術博客</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Fri, 03 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.wayne-project.com/tags/linux/index.xml" rel="self" type="application/rss+xml"/><item><title>【find】在 Linux 使用 find 指令尋找目錄或檔案的速查筆記</title><link>https://blog.wayne-project.com/2023-03-03/linux-find/</link><pubDate>Fri, 03 Mar 2023 00:00:00 +0000</pubDate><guid>https://blog.wayne-project.com/2023-03-03/linux-find/</guid><description>&lt;img src="https://live.staticflickr.com/65535/52722272752_8d023c0dc1_o.jpg" alt="Featured image of post 【find】在 Linux 使用 find 指令尋找目錄或檔案的速查筆記" /&gt;&lt;style&gt;
.article-content p code {
background-color: #f5f5f5;
color: #ff3860;
}
.focus {
background: #f1e2e2;
color: #d62c2c;
padding: 0 5px;
}
.text-center {
text-align: center !important;
}
&lt;/style&gt;
&lt;p&gt;&lt;a class="link" href="https://help.ubuntu.com/community/find" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://linuxize.com/post/how-to-find-files-in-linux-using-the-command-line/" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://blog.miniasp.com/post/2010/08/27/Linux-find-command-tips-and-notice" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在 Linux 平台下找檔案不外乎使用威力強大的 &lt;a class="link" href="https://help.ubuntu.com/community/find" target="_blank" rel="noopener"
&gt;find&lt;/a&gt; 命令，威力強大的背後就是有一點點學習曲線，不過整體上來說還算簡單，因此想寫一篇文章留下備忘，讓自己日後可以快速查閱參考。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="基本語法"&gt;基本語法&lt;/h2&gt;
&lt;p&gt;查詢檔案名稱 (也可以查詢「目錄名稱」，&lt;strong&gt;其中 * 是萬用字元&lt;/strong&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -name &lt;span class="s1"&gt;&amp;#39;*.mp3&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;span class="focus"&gt;註：$HOME 是 Linux 下的一個環境變數，預設指向執行帳號的 HOME 目錄&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id="查詢檔案名稱-不區分大小寫"&gt;查詢檔案名稱 (不區分大小寫)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /etc -iname &lt;span class="s1"&gt;&amp;#39;Network&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="指定只要搜尋檔案名稱"&gt;指定只要搜尋「&lt;strong&gt;檔案&lt;/strong&gt;」名稱&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /var/log -iname &lt;span class="s1"&gt;&amp;#39;*.log&amp;#39;&lt;/span&gt; -type f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="指定只要搜尋目錄名稱"&gt;指定只要搜尋「&lt;strong&gt;目錄&lt;/strong&gt;」名稱&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /etc -iname &lt;span class="s1"&gt;&amp;#39;apache2&amp;#39;&lt;/span&gt; -type d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;補充說明：可用的 &lt;code&gt;-type&lt;/code&gt; 參數值如下&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指令參數&lt;/th&gt;
&lt;th&gt;說明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;td&gt;block (buffered) special&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;td&gt;character (unbuffered) special&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;directory (一般目錄)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;td&gt;named pipe (FIFO)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;f&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;regular file (一般檔案)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;l&lt;/td&gt;
&lt;td&gt;symbolic link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;socket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;door (Solaris)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="找尋所有檔案大小大於-50mb-的檔案"&gt;找尋所有檔案大小&lt;strong&gt;大於 50MB&lt;/strong&gt; 的檔案&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /var -type f -size +50M
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;span class="focus"&gt;註：不加上 -name 參數即代表搜尋所有檔案&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id="找尋所有檔案大小小於-50mb-的檔案"&gt;找尋所有檔案大小&lt;strong&gt;小於 50MB&lt;/strong&gt; 的檔案&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /var -type f -size -50M
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找超過-7-天沒有被存取或修改過的檔案-判斷檔案存取時間"&gt;尋找&lt;strong&gt;超過 7 天沒有被存取或修改過&lt;/strong&gt;的檔案 (判斷檔案存取時間)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -atime +7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找曾經在-7-天內被存取或修改過的檔案-判斷檔案存取時間"&gt;尋找&lt;strong&gt;曾經在 7 天內被存取或修改過&lt;/strong&gt;的檔案 (判斷檔案存取時間)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -atime -7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找超過-10-分鐘沒有被存取或修改過的檔案-判斷檔案存取時間"&gt;尋找&lt;strong&gt;超過 10 分鐘沒有被存取或修改過&lt;/strong&gt;的檔案 (判斷檔案存取時間)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -amin +10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找曾經在-10-分鐘內被存取或修改過的檔案-判斷檔案存取時間"&gt;尋找&lt;strong&gt;曾經在 10 分鐘內被存取或修改過&lt;/strong&gt;的檔案 (判斷檔案存取時間)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -amin -10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找檔案的檔案"&gt;尋找&lt;strong&gt;檔案&lt;span class="focus"&gt;建立時間&lt;/span&gt;已超過 30 天&lt;/strong&gt;的檔案&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -ctime +30
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="尋找特定使用者的檔案-以帳號名稱-wayne-為例"&gt;尋找&lt;strong&gt;特定使用者&lt;/strong&gt;的檔案 (以帳號名稱 wayne 為例)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -type f -user wayne
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="進階應用"&gt;進階應用&lt;/h2&gt;
&lt;h3 id="刪除-30-天以上未經存取過的暫存檔案"&gt;&lt;strong&gt;刪除 30 天以上未經存取過&lt;/strong&gt;的暫存檔案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;注意：以下指令最後一個分號(&lt;span class="focus"&gt;;&lt;/span&gt;)前一定要加上反斜線&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /tmp -type f -atime +30 -print -exec rm -f &lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;加上 &lt;strong&gt;-print&lt;/strong&gt; 是為了讓被刪除的檔案檔名一併顯示在畫面上，這個參數可以省略&lt;/li&gt;
&lt;li&gt;使用 &lt;strong&gt;-exec&lt;/strong&gt; 會讓查詢到的每一個檔案路徑代入 &lt;strong&gt;{}&lt;/strong&gt; 位置，一個檔案會執行一遍 &lt;strong&gt;rm&lt;/strong&gt; 命令&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="刪除-30-天以上未經存取過的暫存檔案-1"&gt;&lt;strong&gt;刪除 30 天以上未經存取過&lt;/strong&gt;的暫存檔案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;使用 &lt;span class="focus"&gt;xargs&lt;/span&gt; 當成單一命令的參數&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /tmp -type f -print0 &lt;span class="p"&gt;|&lt;/span&gt; xargs -0 rm -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;加上 &lt;strong&gt;-print0&lt;/strong&gt; 是為了讓輸出的結果不以「斷行字元」分隔，而改以 &lt;strong&gt;null&lt;/strong&gt; 為結果的分隔字元&lt;/li&gt;
&lt;li&gt;使用 &lt;strong&gt;xargs&lt;/strong&gt; 命令加上 &lt;strong&gt;-0&lt;/strong&gt; 是為了讓傳入的資料以 &lt;strong&gt;null&lt;/strong&gt; 字元當成參數的分隔&lt;/li&gt;
&lt;li&gt;使用 &lt;strong&gt;rm&lt;/strong&gt; 命令加上 &lt;strong&gt;-v&lt;/strong&gt; 是為了能顯示出被刪除的檔案名稱，這個參數可以省略&lt;/li&gt;
&lt;li&gt;使用 &lt;strong&gt;xargs&lt;/strong&gt; 會將所有 &lt;strong&gt;find&lt;/strong&gt; 命令查到的檔案轉換成 &lt;strong&gt;rm&lt;/strong&gt; 的參數列，如果檔案過多可能會執行失敗!&lt;/li&gt;
&lt;li&gt;使用 &lt;strong&gt;xargs&lt;/strong&gt; 可確保後面的程式 (&lt;strong&gt;rm&lt;/strong&gt;) 只執行一次，所以理論上執行速度較快！&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;相同參數需輸入多筆並且以「或」邏輯運算時要用 &lt;strong&gt;-o&lt;/strong&gt; 參數串接起來。&lt;/p&gt;
&lt;p&gt;例(一)：同時找兩種檔名樣式的檔案&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -name &lt;span class="s1"&gt;&amp;#39;*.mp3&amp;#39;&lt;/span&gt; -o -name &lt;span class="s1"&gt;&amp;#39;*.ogg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;例(二)：同時找兩個擁有者的檔案&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find /usr/local -user user1 -o -user user2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="注意事項"&gt;注意事項&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;使用萬用字元時務必加上單引號( &lt;span class="focus"&gt;&amp;rsquo;&lt;/span&gt; )&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="focus"&gt;！！！以下是錯誤示範！！！&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find &lt;span class="nv"&gt;$HOME&lt;/span&gt; -name *.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;</description></item><item><title>每天都在用的 Ping 命令，它到底是什麼？</title><link>https://blog.wayne-project.com/2023-02-08/what-is-ping/</link><pubDate>Wed, 08 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.wayne-project.com/2023-02-08/what-is-ping/</guid><description>&lt;img src="https://live.staticflickr.com/65535/52676255219_5b0b2d891c_o.jpg" alt="Featured image of post 每天都在用的 Ping 命令，它到底是什麼？" /&gt;&lt;style&gt;
.article-content p code {
background-color: #f5f5f5;
color: #ff3860;
}
.focus {
background: #f1e2e2;
color: #d62c2c;
padding: 0 5px;
}
.text-center {
text-align: center !important;
}
&lt;/style&gt;
&lt;p&gt;&lt;a class="link" href="http://www.52im.net/thread-610-1-3.html" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="http://www.52im.net/thread-145-1-1.html" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://zhuanlan.zhihu.com/p/45110873" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675459897_504da451b5_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;老於網絡編程熟手來說，在測試和部署網絡通信應用（比如IM聊天、實時音視頻等）時，如果發現網絡連接超時，第一時間想到的就是使用&lt;strong&gt;Ping&lt;/strong&gt;命令，Ping一下服務器看看通不通。甚至在有些情況下通過圖形化的Ping命令工具對目標網絡進行長測（比如：《&lt;a class="link" href="http://www.52im.net/thread-610-1-3.html" target="_blank" rel="noopener"
&gt;兩款增強型Ping工具：持續統計、圖形化展式網絡狀況[附件下載]&lt;/a&gt;》、《&lt;a class="link" href="http://www.52im.net/thread-145-1-1.html" target="_blank" rel="noopener"
&gt;網絡測試：Android版多路ping命令工具EnterprisePing[附件下載]&lt;/a&gt;》），可以得出當前網絡通信的&lt;code&gt;網絡延遲&lt;/code&gt;、&lt;code&gt;網絡丟包率&lt;/code&gt;、&lt;code&gt;網絡抖動&lt;/code&gt;等等有價值信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52676399005_8f1afb4ba8_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ping命令很簡單，但作為為數不多的網絡檢測工具，卻非常有用，是開發網絡應用時最常用到的命令。雖然Ping這個動作這麼簡單，但你知道Ping命令背後後的邏輯嗎？跟著本篇文章瞭解一下！&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ping命令的作用和原理"&gt;Ping命令的作用和原理&lt;/h2&gt;
&lt;p&gt;簡單來說，「&lt;strong&gt;ping&lt;/strong&gt;」是用來探測本機與網絡中另一主機之間是否可達的命令，如果兩台主機之間ping不通，則表明這兩台主機不能建立起連接。ping是定位網絡通不通的一個重要手段。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675459902_abcb6f9909_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;ping 命令是基於 &lt;strong&gt;ICMP 協議&lt;/strong&gt;來工作的，「&lt;strong&gt;ICMP&lt;/strong&gt;」全稱為Internet 控制報文協議（&lt;a class="link" href="https://tools.ietf.org/html/rfc792" target="_blank" rel="noopener"
&gt;Internet Control Message Protocol&lt;/a&gt;）。ping 命令會發送一份ICMP回顯請求報文給目標主機，並等待目標主機返回ICMP回顯應答。因為ICMP協議會要求目標主機在收到消息之後，必須返回ICMP應答消息給源主機，如果源主機在一定時間內收到了目標主機的應答，則表明兩台主機之間網絡是可達的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;舉一個例子來描述「ping」命令的工作過程：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;假設有兩個主機，主機A（192.168.0.1）和主機B（192.168.0.2），現在我們要監測主機A和主機B之間網絡&lt;strong&gt;是否可達&lt;/strong&gt;，那麼我們在主機A上輸入命令：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ping 192.168.0.2。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;
&lt;p&gt;此時，ping 命令會在主機A上構建一個&lt;strong&gt;ICMP&lt;/strong&gt;的&lt;strong&gt;請求數據包&lt;/strong&gt;（數據包裡的內容後面再詳述），然後ICMP協議會將這個&lt;strong&gt;數據包&lt;/strong&gt;以及&lt;strong&gt;目標IP&lt;/strong&gt;（192.168.0.2）等信息一同交給IP層協議。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IP層協議得到這些信息後，將&lt;strong&gt;源地址&lt;/strong&gt;（即本機IP）、&lt;strong&gt;目標地址&lt;/strong&gt;（即目標IP：192.168.0.2）、再加上一些其它的&lt;strong&gt;控制信息&lt;/strong&gt;，構建成一個&lt;strong&gt;IP數據包&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IP數據包構建完成後，還不夠，還需要加上&lt;code&gt;MAC地址&lt;/code&gt;，因此，還需要通過ARP映射表找出&lt;strong&gt;目標IP所對應的MAC地址&lt;/strong&gt;。當拿到了&lt;strong&gt;目標主機的MAC地址&lt;/strong&gt;和&lt;strong&gt;本機MAC&lt;/strong&gt;後，一併交給數據鏈路層，組裝成一個&lt;strong&gt;數據幀&lt;/strong&gt;，依據以太網的介質訪問規則，將它們傳送出出去。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;當主機B收到這個數據幀之後，會首先檢查它的&lt;strong&gt;目標MAC地址是不是本機&lt;/strong&gt;，如果是，就接收下來處理，接收之後會檢查這個數據幀，將數據幀中的&lt;strong&gt;IP數據包&lt;/strong&gt;取出來，交給本機的&lt;strong&gt;IP層協議&lt;/strong&gt;，然後IP層協議檢查完之後，再將&lt;strong&gt;ICMP數據包&lt;/strong&gt;取出來交給&lt;strong&gt;ICMP協議&lt;/strong&gt;處理，當這一步也處理完成之後，就會構建一個&lt;strong&gt;ICMP應答數據包&lt;/strong&gt;，回發給主機A。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在一定的時間內，如果主機A收到了應答包，則說明它與主機B之間網絡可達；如果沒有收到，則說明網絡不可達。除了監測是否可達以外，還可以利用&lt;strong&gt;應答時間&lt;/strong&gt;和&lt;strong&gt;發起時間&lt;/strong&gt;之間的差值，計算出數據包的&lt;strong&gt;延遲耗時&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;通過 ping 的流程可以發現，ICMP協議是這個過程的基礎，是非常重要的，下面的章節會把ICMP協議再詳細解釋一下，請繼續往下讀。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="正確理解icmp協議"&gt;正確理解ICMP協議&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ping命令所基於的ICMP協議所處的網絡模型層級：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675969646_55ce44a2f4_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;（▲ 上圖來自《&lt;a class="link" href="http://www.52im.net/thread-180-1-1.html" target="_blank" rel="noopener"
&gt;計算機網絡通訊協議關係圖（中文珍藏版）[附件下載]&lt;/a&gt;》，您可下載此圖的完整清晰版）&lt;/p&gt;
&lt;p&gt;Ping 命令這麼簡單，在任何系統上上手就能使用，很多人可能想當然的認為 Ping 命令使用的&lt;strong&gt;ICMP協議&lt;/strong&gt;應該是基於傳輸層的TCP或UDP協議的吧？&lt;/p&gt;
&lt;p&gt;正如上圖所示，&lt;strong&gt;ICMP協議&lt;/strong&gt;既&lt;strong&gt;不是基於TCP&lt;/strong&gt;，也&lt;strong&gt;不是基於UDP&lt;/strong&gt;，而是&lt;code&gt;直接基於網絡層的IP協議&lt;/code&gt;，在整個網絡協議棧中屬於相當底層的協議了。這也從側面證明了它的重要性，因為根據ICMP的&lt;a class="link" href="https://tools.ietf.org/html/rfc792" target="_blank" rel="noopener"
&gt;RFC手冊&lt;/a&gt;規定：&lt;strong&gt;ICMP協議是任何支持IP協議的系統必須實現的&lt;/strong&gt;，沒有餘地。而IP協議是整個互聯網的基石，ICMP協議雖簡單，但重要性不言而喻。&lt;/p&gt;
&lt;p&gt;所以，以後面試的時候，如果碰到&amp;quot;ICMP協議是基於什麼實現的？&amp;ldquo;這樣的問題，請一定要記往此節所講的內容。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="深入icmp協議"&gt;深入ICMP協議&lt;/h2&gt;
&lt;p&gt;我們知道，ping 命令是基於&lt;strong&gt;ICMP協議&lt;/strong&gt;來實現的。那麼我們再來看下圖，就明白了ICMP協議又是通過IP協議來發送的，即ICMP報文是封裝在IP包中（如下圖所示）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675969706_f406206ed8_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;IP協議是一種無連接的，不可靠的數據包協議，它並不能保證數據一定被送達，那麼我們要保證數據送到，就需要通過其它模塊來協助實現，這裡就引入的是&lt;strong&gt;ICMP協議&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;當傳送的IP數據包發送異常的時候，ICMP就會將異常信息封裝在包內，然後回傳給源主機。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;將上圖再細拆一下可見：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675969701_5ca4982b3b_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;繼續將ICMP協議模塊細拆：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52676462808_8cfe4e9fdd_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;由圖可知，&lt;code&gt;ICMP數據包&lt;/code&gt;由&lt;strong&gt;8bit的類型字段&lt;/strong&gt;和&lt;strong&gt;8bit的代碼字段&lt;/strong&gt;以及&lt;strong&gt;16bit的校驗字段&lt;/strong&gt;再加上&lt;strong&gt;選項數據&lt;/strong&gt;組成。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ICMP協議大致可分為兩類：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;查詢報文類型&lt;/li&gt;
&lt;li&gt;差錯報文類型&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;ICMP報文類型&lt;/td&gt;
&lt;td class="text-center"&gt;類型的值&lt;/td&gt;
&lt;td class="text-center"&gt;ICMP的報文類型&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td rowspan="5" class="text-center"&gt;差錯報文類型&lt;/td&gt;
&lt;td class="text-center"&gt;3&lt;/td&gt;
&lt;td class="text-center"&gt;終點不可達&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;4&lt;/td&gt;
&lt;td class="text-center"&gt;源點抑制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;11&lt;/td&gt;
&lt;td class="text-center"&gt;時間超過&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;12&lt;/td&gt;
&lt;td class="text-center"&gt;參數問題&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;5&lt;/td&gt;
&lt;td class="text-center"&gt;改變路由&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan="4" class="text-center"&gt;詢問報文&lt;/td&gt;
&lt;td class="text-center"&gt;8&lt;/td&gt;
&lt;td class="text-center"&gt;回送請求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;0&lt;/td&gt;
&lt;td class="text-center"&gt;回送回答&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;13&lt;/td&gt;
&lt;td class="text-center"&gt;時間戳請求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="text-center"&gt;14&lt;/td&gt;
&lt;td class="text-center"&gt;時間戳會帶&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;【關於查詢報文類型】：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查詢報文主要應用於：&lt;code&gt;ping 查詢&lt;/code&gt;、&lt;code&gt;子網掩碼查詢&lt;/code&gt;、&lt;code&gt;時間戳查詢&lt;/code&gt;等等。&lt;/p&gt;
&lt;p&gt;上面講到的 ping 命令的流程其實就對應ICMP協議查詢報文類型的一種使用。在主機A構建ICMP請求數據包的時候，其ICMP的類型字段中使用的是8 （回送請求），當主機B構建ICMP應答包的時候，其ICMP類型字段就使用的是0 （回送應答），更多類型值參考上表。&lt;/p&gt;
&lt;p&gt;對查詢報文類型的理解可參考一下文章最開始講的 ping 流程，這裡就不做贅述。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;【關於差錯報文類型】：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;差錯報文主要產生於當數據傳送發送錯誤的時候。&lt;/p&gt;
&lt;p&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;/p&gt;
&lt;p&gt;差錯報文通常包含了引起錯誤的IP數據包的第一個分片的IP首部，加上該分片數據部分的前8個字節。&lt;/p&gt;
&lt;p&gt;當傳送IP數據包發生錯誤的時候（例如主機不可達），ICMP協議就會把錯誤信息封包，然後傳送回源主機，那麼源主機就知道該怎麼處理了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="icmp差錯報文的妙用"&gt;ICMP差錯報文的妙用&lt;/h2&gt;
&lt;p&gt;正如上一節所介紹的那樣，ICMP協議主要有：&lt;strong&gt;查詢報文類型&lt;/strong&gt;和&lt;strong&gt;差錯報文類型&lt;/strong&gt;兩種。對於差錯報文來說，是不是只有遇到錯誤的時候才能使用呢？&lt;strong&gt;不是&lt;/strong&gt;！&lt;/p&gt;
&lt;p&gt;基於這個特性，Linux 下的 &lt;strong&gt;Traceroute&lt;/strong&gt; 指令（Windows 下的對等指令是 &lt;strong&gt;tracert&lt;/strong&gt;）利於ICMP的差錯報文可以實現&lt;strong&gt;遍歷到數據包傳輸路徑上的所有路由器&lt;/strong&gt;！這真是個有用的命令！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;百度百科上關於 traceroute 命令的用途：&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;traceroute (Windows 系統下是 tracert) 命令利用 ICMP 協議定位您的計算機和目標計算機之間的所有路由器。TTL 值可以反映數據包&lt;strong&gt;經過的路由器&lt;/strong&gt;或&lt;strong&gt;網關的數量&lt;/strong&gt;，通過操縱獨立 ICMP 呼叫報文的 TTL 值和觀察該報文被拋棄的返回信息，&lt;strong&gt;traceroute 命令能夠遍歷到數據包傳輸路徑上的所有路由器&lt;/strong&gt;。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;ICMP 的差錯報文的使用，使得 &lt;strong&gt;Traceroute&lt;/strong&gt; 成為用來&lt;strong&gt;偵測源主機到目標主機之間所經過路由情況&lt;/strong&gt;的常用工具。&lt;strong&gt;Traceroute&lt;/strong&gt; 的原理就是利用ICMP的規則，製造一些錯誤的事件出來，然後根據錯誤的事件來評估網絡路由情況。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;traceroute 的基本原理如下圖所示：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52676399055_bc21725b99_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://live.staticflickr.com/65535/52675969651_8fcea78cf5_o.jpg"
max-width="100%"
max-height="100%"
class="gallery-image"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;具體做法就是：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traceroute&lt;/strong&gt; 會設置特殊的 TTL 值，來追踪源主機和目標主機之間的路由數。首先它給目標主機發送一個 TTL=1 的UDP數據包，那麼這個數據包一旦在路上遇到一個路由器，TTL 就變成了 0（TTL規則是每經過一個路由器都會減1），因為 TTL=0 了，所以路由器就會把這個數據包丟掉，然後產生一個錯誤類型（超時）的ICMP數據包回發給源主機，也就是差錯包。這個時候源主機就拿到了第一個路由節點的IP和相關信息了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接著，源主機再給目標主機發一個 TTL=2 的UDP數據包，依舊上述流程走一遍，就知道第二個路由節點的IP和耗時情況等信息了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如此反復進行，&lt;strong&gt;Traceroute&lt;/strong&gt; 就可以拿到從主機A到主機B之間所有路由器的信息了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是有個問題是，如果數據包到達了目標主機的話，即使目標主機接收到 TTL 值為 1 的IP數據包，它也是不會丟棄該數據包的，也不會產生一份超時的ICMP回發數據包的，因為數據包已經達到了目的地嘛。那我們應該怎麼認定數據包是否達到了目標主機呢？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Traceroute&lt;/strong&gt; 的方法是在源主機發送UDP數據包給目標主機的時候，會設置一個&lt;strong&gt;不可能達到的目標端口號&lt;/strong&gt;（例如大於30000的端口號），那麼當這個數據包真的到達目標主機的時候，目標主機發現沒有對應的端口號，因此會產生一份&lt;code&gt;端口不可達&lt;/code&gt;的錯誤ICMP報文返回給源主機。&lt;/p&gt;
&lt;p&gt;可見 &lt;strong&gt;Traceroute&lt;/strong&gt; 的原理確實很取巧，很有趣。如您對 &lt;strong&gt;Traceroute&lt;/strong&gt; 感興趣，可以深入讀一讀《&lt;a class="link" href="https://cloud.tencent.com/developer/article/1004762" target="_blank" rel="noopener"
&gt;從 Traceroute 看網絡問題&lt;/a&gt;》一文。&lt;/p&gt;
&lt;hr&gt;</description></item><item><title>3 種使用 Regex 正則表達式對資料夾中的文字檔進行搜尋與取代的方法</title><link>https://blog.wayne-project.com/2023-02-03/replace-using-regex-in-3-ways/</link><pubDate>Fri, 03 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.wayne-project.com/2023-02-03/replace-using-regex-in-3-ways/</guid><description>&lt;img src="https://live.staticflickr.com/65535/52666393963_8b2453a1b5_o.jpg" alt="Featured image of post 3 種使用 Regex 正則表達式對資料夾中的文字檔進行搜尋與取代的方法" /&gt;&lt;style&gt;
.article-content p code {
background-color: #f5f5f5;
color: #ff3860;
}
.focus {
background: #f1e2e2;
color: #d62c2c;
padding: 0 5px;
}
&lt;/style&gt;
&lt;p&gt;&lt;a class="link" href="https://officeguide.cc/linux-sed-find-and-replace-text-in-file-tutorial-examples/" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/adamreisnz/replace-in-file" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://www.npmjs.com/package/replace-in-file" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://man7.org/linux/man-pages/man1/sed.1.html" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://blog.miniasp.com/post/2023/02/02/How-to-search-and-replace-using-regex-in-3-ways" target="_blank" rel="noopener"
&gt;參考網站&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在整理開發環境的時候，經常會有批次調整檔案內容的需求，我今天特別整理了 3 種不同的解決方案，這些方法都可以看情況使用！&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="linux--wsl"&gt;Linux / WSL&lt;/h2&gt;
&lt;p&gt;在 Linux 環境下使用 &lt;code&gt;find&lt;/code&gt; 與 &lt;code&gt;sed&lt;/code&gt; 幾乎是標準方案，這套組合拳確實快速又強大！👍&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;find src -name &lt;span class="s1"&gt;&amp;#39;*.ts&amp;#39;&lt;/span&gt; -type f -exec sed -i &lt;span class="s1"&gt;&amp;#39;s/pattern\([s]\)/replacement\1/g&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;透過 &lt;code&gt;sed&lt;/code&gt; 來取代內容的話，在 &lt;strong&gt;Regex&lt;/strong&gt; 語法上稍微有點不同，左邊的小括弧要加上反斜線跳脫 ( &lt;code&gt;\(&lt;/code&gt; 或 &lt;code&gt;\)&lt;/code&gt; )，而 backreference 也要用反斜線來表達 ( &lt;code&gt;\1&lt;/code&gt;、&lt;code&gt;\2&lt;/code&gt;、&amp;hellip; )&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="windows-powershell"&gt;Windows (PowerShell)&lt;/h2&gt;
&lt;p&gt;在 Windows 上面使用 PowerShell 來寫腳本，可讀性會比較好！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Get-ChildItem -Path &lt;span class="s1"&gt;&amp;#39;src&amp;#39;&lt;/span&gt; -Include &lt;span class="s1"&gt;&amp;#39;*.ts&amp;#39;&lt;/span&gt; -Recurse -Exclude reparsepoint &lt;span class="p"&gt;|&lt;/span&gt; ForEach-Object &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;$current_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;.FullName&lt;span class="k"&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="nv"&gt;$replace_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;.FullName&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.new&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;# 這裡 Get-Content 前後的小括弧很重要，一定要加上才能得到 String 的結果，指定 utf8 編碼也十分重要！&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;Get-Content -LiteralPath &lt;span class="nv"&gt;$current_file&lt;/span&gt; -Encoding utf8&lt;span class="o"&gt;)&lt;/span&gt; -replace &lt;span class="s1"&gt;&amp;#39;pattern([s])&amp;#39;&lt;/span&gt;, &lt;span class="s1"&gt;&amp;#39;replacement$1&amp;#39;&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; Out-File -Encoding utf8 -LiteralPath &lt;span class="nv"&gt;$replace_file&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; Move-Item -LiteralPath &lt;span class="nv"&gt;$replace_file&lt;/span&gt; -Destination &lt;span class="nv"&gt;$current_file&lt;/span&gt; -Force
&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="nodejs"&gt;Node.js&lt;/h2&gt;
&lt;p&gt;如果我們要在前端專案中整合字串取代的工作，在 &lt;strong&gt;package.json&lt;/strong&gt; 的 &lt;strong&gt;scripts&lt;/strong&gt; 直接取代檔案，同時又要兼顧跨平台的話，採用既有的 npm 套件就會來的方便許多。這裡我找了個 &lt;a class="link" href="https://www.npmjs.com/package/replace-in-file" target="_blank" rel="noopener"
&gt;replace-in-file&lt;/a&gt; 套件還不錯！👍&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先安裝到專案中：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;npm install -D replace-in-file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;取代內容可以這樣寫，也可以使用超好用的 Glob 語法(e.g. &lt;code&gt;src/**/*.ts&lt;/code&gt;)：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;npx replace-in-file &lt;span class="s2"&gt;&amp;#34;/pattern([s])/g&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;replacement&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; src/**/*.ts --isRegex --encoding&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item></channel></rss>