在 Linux 系統程式設計中,ls 是最基礎也最常用的指令之一。本文將帶領你從零開始,使用 C 語言實作一個支援 -l、-a、-i、-R、-t、-r 等常見參數的 ls 指令模擬程式。透過這個專案,你將深入理解目錄讀取、檔案屬性獲取、位元旗標處理、遞迴遍歷以及終端機輸出格式化等核心系統程式設計技巧。
程式使用位元遮罩來管理各參數狀態,定義於標頭檔區塊:
#define LL (1<<0) /* -l 參數:長格式顯示 */
#define IL (1<<1) /* -i 參數:顯示 inode 號 */
#define RU (1<<2) /* -R 參數:遞迴列出子目錄 */
#define TL (1<<16) /* -t 參數:依修改時間排序 */
#define AL (1<<17) /* -a 參數:顯示隱藏檔 */
#define RL (1<<18) /* -r 參數:反向排序 */
#define LENGTH 500
#define MAX_FILE_COUNT 500
mode 變數的低 16 位控制輸出格式,高 16 位控制排序與篩選行為,擴充性極佳。
argv,遇到 - 開頭者逐字元對應旗標,否則視為目標路徑。file_list() 使用 opendir/readdir 讀取目錄,配合 stat 取得檔案詳細資訊,並依旗標決定是否略過隱藏檔、按字母/時間排序、反向排序。display() 依 mode 低 3 位(共 8 種組合)呼叫對應的顯示函式,若含 -R 則進入遞迴顯示流程。file_list)chdir 切換工作目錄,簡化後續 stat 呼叫。-t):採選擇排序依 st_mtime 遞減排列。-r):直接對陣列首尾交換。| 函式 | 對應參數 | 說明 |
|---|---|---|
display_simply | 無 | 多欄對齊顯示檔名,自動偵測終端機寬度 (ioctl TIOCGWINSZ) |
display_LL | -l | 完整長格式:權限、連結數、擁有者/群組、大小、修改時間、檔名 |
display_IL | -i | inode 號 + 檔名,多欄對齊 |
display_LL_IL | -li | 長格式前加 inode 號 |
display_RU* | -R 系列 | 遞迴列印:先印當前目錄名,再遞迴處理子目錄,略過 . 與 .. |
採位元測試逐字元輸出,雖程式碼重複,但邏輯清晰,易於維護:
if (S_ISDIR(mode)) printf("d"); else printf("-");
if (mode & (1<<8)) printf("r"); else printf("-");
/* ... 依序處理 user/group/other rwx */
統一使用 error() 函式:記錄行號、輸出 perror 訊息、以 EXIT_FAILURE 結束程式,確保任何系統呼叫失敗皆能即時回報。
gcc -o myls myls.c
./myls -laiR /tmp
即可看到與系統 ls 高度相容的輸出結果。
-h(人類可讀大小)、-S(依大小排序)等參數,只需擴充旗標與排序邏輯。qsort,提升大量檔案時效能。此專案展示了 Linux 系統程式設計的經典範式:目錄操作、檔案屬性、位元旗標、遞迴遍歷、終端機互動。完整程式碼約 300 行,結構清晰,是學習系統程式設計的優良教材。