
Linux 常用指令易用錯:rsync、find、sort、tar 的安全操作
XDA Developers 作者 Joe Rice-Jones 以 Debian 13 容器測試 rsync、find、sort 與 tar,發現許多看似熟悉的指令,問題不在語法能否執行,而在常用旗標是否真的符合工作目的。這對管理備份、自架環境或日常整理檔案的人都有直接影響:指令沒有報錯,不代表複製內容完整、搜尋過程有效率,或排序結果可用。
不過,文中若干速度、檔案數量及傳輸結果均屬作者在特定測試環境下的觀察,不能當成不同 Linux 發行版、儲存裝置或網絡環境的通用效能保證。較值得借鏡的是驗證方法:在會改動檔案前先預覽,在輸出反常時查看程式實際比較了甚麼,並了解每個旗標改變的預設行為。
rsync:複製、備份與鏡像是三件不同的事
rsync 最常見的 -a 是 archive mode,實際上集合了遞迴、保留符號連結、權限、時間、群組、擁有者及裝置等設定,即 -rlptgoD。作者把同一目錄分別以 -a 和單純 -r 複製,後者略過符號連結,並令檔案時間變成複製當刻。即使某些權限仍獲保留,若目標是可還原的備份,遺失連結與原有修改時間已足以影響日後判斷和還原。
更要小心的是 --delete。它令目標端刪除來源端已不存在的檔案,因而可製作鏡像;同時也意味來源路徑、目標路徑或掛載狀態一旦判斷錯誤,刪除會跟著執行。較穩妥的流程是先加入 --dry-run,配合 -i 逐項列出變更,先確認將被移除和更新的路徑,再決定是否拿走預覽旗標。作者測試中,*deleting 會指出待刪檔案,而類似 >f..t...... 的代碼可反映檔案只因時間不同而更新;第一次看雖難讀,卻比事後追查刪錯檔案可靠得多。
中途中斷的大型傳輸則涉及另一個取捨。--partial 會保留未完成檔案,-P 亦包含進度顯示;作者在限速測試中中止複製後,保留下來的部分資料可供其後傳輸重用。原文亦提醒,本機複製預設可能採用 whole-file 傳輸,如要利用部分檔案續傳,測試時需加上 --no-whole-file。至於備份整個根目錄,-x 會限制 rsync 留在同一檔案系統,避免走進 /proc、/sys 和 /dev 等虛擬或特殊檔案系統;是否應排除其他掛載點,仍要按還原需求逐一決定。
find:篩選結果不等於減少搜尋工作
find 的兩個陷阱都關乎程式到底有沒有走進目錄。-exec ... {} \; 會對每個找到的檔案各啟動一次外部程式;改為 -exec ... {} +,則會把多個路徑合併至較少次呼叫。作者以 1,000 個檔案比較 ls -l,前者約需 0.348 秒,後者約需 0.006 秒。數字本身不宜外推,但大量重複啟動程序會累積成本,這個差異很有參考價值。
排除大型目錄時亦不能只看最終輸出。以 -not -path 排除 node_modules,可令該路徑不顯示,卻未必阻止 find 逐一掃過其內檔案;-prune 的作用是停止遞迴進入指定目錄。作者記錄檢查項目後發現,兩種寫法找到相同六個目標,但前者走訪 20,011 個項目,後者只有 11 個。寫自動化清理或稽核腳本前,應先分清「隱藏結果」和「不作遍歷」這兩層意思。
GNU find 亦可用 -printf 直接輸出日期、大小、權限和路徑,減少再配合 ls 或 stat 輸出並解析文字的需要;-newer 與 -newermt 則可按標記檔案或日期找出較新的檔案。要留意 -printf 是 GNU 擴充功能,原文指出 macOS 隨附的 find 未必支援。另加上 -fprint、-exec 等動作後,find 的預設輸出會停用;若仍要在終端看見結果,須明確加入 -print。
sort:選錯比較方式,清單可以整齊地出錯
排序尤其容易給人「結果看來合理」的錯覺。du -sh 產生的大小帶有 K、M、G 等單位,若接上 sort -n,程式只按開頭數字比較;因此 1.1GB 可被排到 2.0、12 或 46 之前。對人類可讀的容量,應使用理解單位的 sort -h;若目標是由大至小找出最佔空間的項目,還要加入反向排序設定。這是資料格式與比較規則不匹配,不是磁碟用量計算出了問題。
版本字串亦不宜交給一般文字排序。原文舉例,文字比較會把 app-1.10 放在 app-1.2 前,亦可能令 app-10.1 早於 app-2.0;sort -V 會按版本號的數字段落處理,較貼近日常閱讀次序。當排序結果令人懷疑時,--debug 可標示實際被用來比較的欄位,亦可揭示 locale 設定失敗後回退至 byte comparison 的情況。涉及重音字、大小寫或多語文字的清單,這類環境差異有機會令不同機器得出不同次序。
多重排序還有穩定性問題。作者先按分數、再按隊伍排序時,沒有 -s 的後一次排序可因隱含的整行比較而打亂同隊原有的分數次序。較清楚的做法是一次指定所有鍵,例如以分隔符配合 -k,先按隊伍、再按分數逆序排序;若確實需要分兩次處理,則以 stable sort 保留第一次的既有順序。重點是按報表或處理需要,明確設定排序鍵,別依賴肉眼推測預設行為。
tar:讓副檔名與路徑規則代替記憶口訣
tar 的壓縮旗標經常靠肌肉記憶輸入,但 gzip、xz 等格式需要的旗標不同。作者建議建立封存檔時使用 -a,由檔名副檔名自動選擇壓縮器,例如 .tar.gz 或 .tar.xz;讀取時,tar -tf 與 tar -xf 可自行偵測壓縮格式,毋須每次重複加入對應解壓旗標。這可降低把 -z 和 -J 輸錯的機會,但檔名仍應如實反映所選格式,方便交接和日後維護。
解封時的路徑處理同樣重要。--strip-components=1 可移除封存檔內最外層的一級目錄,-C 可指定解封目的地,不必先切換工作目錄;--transform 則能在建立封存檔時以類似 sed 的規則改寫路徑。這些選項適合部署或備份腳本,但也意味檔案最後落點未必與封存內看到的路徑一致。執行前先以 tar -tf 列出內容,核對層級與名稱,會比事後在錯誤位置尋找檔案省時。
這組經驗的下一步,不是盲目換另一套工具,而是把既有指令分成「預覽」、「執行」和「驗證」三個階段:rsync 先 dry run,find 先確認遍歷範圍,sort 先核對鍵與單位,tar 先列出封存內容。對依賴 shell 歷史、排程腳本或自架環境的人而言,最值得持續檢查的將是舊有 alias 和自動化命令:每一個短旗標仍是否表達目前真正要做的事。
延伸閱讀
AI 輔助說明: 本文由 AI 協助整理,並經兩輪獨立自動品質審核;資料及連結仍以原始來源為準。
參考來源
- XDA Developers — I was using rsync, find, sort, and tar wrong until I learned what their flags actually do — original report
本文根據原文及公開資料整理;資料有出入時,以原文及官方資料為準。





