一個關於UNIX檔案系統指令集的簡短指南

我寫這份手冊的目標是讓學習、記憶和查詢主要UNIX檔案系統工具更容易。macOS和GNU/Linux都是UNIX系統,在實際應用中。macOS是基於BSD UNIX的認證UNIX,而GNU/Linux是UNIX相似或UNIX衍生。

在介紹檔案系統和它如何運作之後,我將詳細說明以下指令的細節:

處理資料夾和檔案

  • mkdir
  • cd
  • pwd
  • rmdir
  • ls
  • touch
  • mv
  • cp
  • ln

權限

  • chmod
  • chown
  • chgrp

檔案內容

  • cat
  • less
  • find
  • cpio
  • dd
  • wc

檔案系統如何運作

每台現代化的電腦系統都依賴檔案系統以儲存和擷取程式。並非所有的東西都可以儲存在記憶體中,因為它是珍貴和有限的資源。所以,當電腦重新啟動或關機時,我們需要一個安全的地方來存儲資料。

記憶體在每次電腦重新啟動時都會被完全清除,而磁碟結構是持久存在的。

在這份指南中,我將專門介紹UNIX檔案系統,該系統可以在macOS和GNU/Linux機器上找到。Windows的檔案系統是不同的,雖然安裝了Windows子系統的Windows 10允許您使用我在這裡描述的相同工具。

檔案系統始於/ (根目錄)。這是第一層目錄的根節點。

UNIX系統中通常會找到的目錄有

  • /bin 包含主系統指令
  • /etc 包含系統配置
  • /dev 包含系統設備
  • /usr 包含使用者檔案
  • /tmp 包含臨時檔案

當然要根據使用的系統類型的不同而有所不同。Linux 通過其Linux Standard Base的努力使這些目錄時一樣的,您通常有:

  • /bin 主系統指令
  • /boot 用於引導機器的檔案(在macOS上不存在)
  • /dev 系統設備
  • /etc 系統配置檔案
  • /etc/opt 使用者程式配置檔案
  • /home 使用者的家目錄(/Users在macOS上)
  • /lib 系統庫(在macOS上不存在)
  • /mnt 掛載的檔案系統
  • /opt 使用者程式
  • /proc 系統由內核和程序(在macOS上不存在)
  • /root 系統管理者的家目錄(在macOS上不存在)
  • /run (在macOS上不存在)
  • /sbin 開機系統二進制檔案
  • /tmp 臨時檔案
  • /usr 包含使用者軟件、庫和工具
  • /usr/bin 使用者二進制檔案
  • /usr/include 使用者頭檔案
  • /usr/lib 使用者庫
  • /usr/local 由使用者軟件用於儲存安裝,像在macOS上的Homebrew
  • /usr/sbin 系統二進制檔案
  • /usr/share 包含與架構無關的資料,可能包含大量的其他資訊,包括文件和手冊
  • /usr/src 包含已安裝套件的原始碼(在macOS上不存在)
  • /var 包含臨時檔案,日誌等

macOS有很多不同的目錄,包括

  • /Applications 存放使用者應用程式
  • /Library 存放系統的全域使用圖書館(設置和資源)
  • /System 存放系統檔案
  • /private 存放系統檔案,日誌等

每個目錄都包含檔案和子目錄,這些子目錄本身又可以包含其他檔案和子目錄,依此類推。

所有的檔案和目錄都有一個名字。

什麼是一個有效的名字? 它可以由1到255個字符組成,必須由任何字母或數字(a-z/A-Z/0-9),底線 (_),點(.) 和逗號(,)字符構成。

您也可以使用空格,但通常不建議使用,因為每次引用檔案/目錄時都必須將空格用反斜線進行轉義。

根據不同的系統,檔案系統可能是區分大小寫的。在macOS上,檔案系統預設為不區分大小寫, 所以您不能有一個名稱為test的檔案/目錄和一個名為Test的檔案/目錄。它們是同一樣東西。

現在我要介紹一些不同的實用指令。這些指令在shell (如Bash、Fish或Zsh)的上下文中執行。當您開啟一個shell時,一般都會在您的家目錄。在macOS中,這個目錄可以在/Users/<您的名字>/路徑中找到。

如果更改所使用的shell,這些指令不會變化,因為這些是UNIX的基本指令。在世界計算的革命發生之前(雖然那種事情確實存在,但那些服務器端的東西通常移動很慢),您往往需要使用這些指令數十年。舉個例子, 您現在將看到的 mkdir 指令引入至UNIX AT&T的第一版中,早於80年代初。

處理資料夾和檔案

mkdir

使用mkdir指令創建資料夾:

mkdir fruit

您可以使用一個指令創建多個資料夾:

mkdir dogs cars

您也可以通過添加-p選項創建多層資料夾:

mkdir -p fruits/apples

UNIX指令中的選項通常採取這種形式。您將它們添加在指令名之後,並通過它們來更改指令的行為。您還可以結合使用多個選項。

您可以通過輸入man <commandname>找到指令所支援的選項。例如,現在嘗試使用man mkdir (按下q鍵退出man頁面)。Man頁是UNIX內置的令人驚歎的幫助文檔。

cd

一旦創建了資料夾,您可以使用cd指令進入資料夾。cd代表change directory(切換目錄)。您調用它指定要移動到的資料夾。您可以指定資料夾名稱或完整路徑。

例子:

mkdir fruits
cd fruits

現在您進入了fruits資料夾。

您可以使用..特殊路徑來指示父資料夾:

cd .. # 返回家目錄

您可以使用它來形成一個路徑:

mkdir fruits
mkdir cars
cd fruits
cd ../cars

還有另一個特殊的路徑指示器.,表示當前資料夾。

您還可以使用絕對路徑,從根資料夾/開始:

cd /etc

pwd

每當您在檔案系統中感到迷失時,使用pwd指令來查看您的位置:

pwd

它將列印出當前資料夾的路徑。

rmdir

就像您可以使用mkdir創建資料夾一樣,您可以使用rmdir指令刪除資料夾:

mkdir fruits
rmdir fruits

您還可以一次刪除多個資料夾:

mkdir fruits cars
rmdir fruits cars

要刪除包含有檔案的資料夾,我們將使用更通用的rm指令來刪除檔案和資料夾,使用-rf選項:

rm -rf fruits cars

請小心,因為該指令不會請求確認,它會立即刪除您要求刪除的所有項目。

如果沒有垃圾桶可用時,删除檔案後將很難恢复丟失的檔案。

ls

在資料夾內,您可以使用ls指令列出資料夾包含的所有檔案:

ls

如果添加檔案名或路徑,它將列印該資料夾的內容:

ls /bin

ls接受很多選項。我最喜歡的選項組合之一是-al。現在試試看:

ls -al /bin

與普通的ls相比,此選項返回更多的資訊。

從左到右,您有:

  • 檔案許可權(如果您的系統支持ACLs,您還會得到ACL標誌)
  • 對該檔案的連結數
  • 檔案的所有者
  • 檔案的群組
  • 檔案的字節大小
  • 檔案的修改日期時間
  • 檔案名稱

此數據集是由l選項生成的。a選項同樣會顯示隱藏的檔案。

隱藏檔案是以點(.)開頭的檔案。

touch

您可以使用touch指令創建一個空檔案:

touch apple

如果檔案已經存在,它會以寫入模式開啟該檔案,並更新檔案的時間戳。

mv

一旦有了檔案,您可以使用mv指令將其移動到其他位置。指定檔案的當前路徑和其新路徑:

touch test
mv pear new_pear

現在pear檔案被移動到new_pear。這是如何重新命名檔案和資料夾的方式。

如果最後一個參數是一個資料夾,位於第一個參數路徑的檔案將移動到該資料夾中。在這種情況下,您可以指定一列檔案,它們將全部被移動到由最後一個參數識別的資料夾路徑中:

touch pear
touch apple
mkdir fruits
mv pear apple fruits #pear和apple移至於fruits資料夾

cp

您可以使用cp指令複製檔案:

touch test
cp apple another_apple

要複製資料夾,您需要在後面添加-r選項,以遞迴複製整個資料夾內容:

mkdir fruits
cp -r fruits cars

ln

現在讓我們介紹鏈結的概念。鏈結是指向其他檔案的檔案。我們在所有主要的操作系統上都有這些。

我們可以創建兩種類型的鏈結:硬鏈結和符號(軟)鏈結。我們無法創建指向資料夾的硬鏈結,但我們可以創建一個符號鏈結。因此,符號鏈結(也稱為symlinks)更為常見。

我們使用以下語法創建符號鏈結:ln -s original linkname。例如:

mkdir fruits
ln -s fruits newfruits

請注意我使用的ll命令。這不是標準命令,但是ls -al的別名。在shell中,您可以定義別名,以便快速執行常見的命令和參數組合。

權限

我之前簡單提到權限,當我介紹ls -al指令時。

您在每個檔案行上看到的奇怪字符串,如drwxr-xr-x,定義了檔案或資料夾的權限。

讓我們來解析它。

第一個字母表示檔案的類型:

  • - 表示它是一個普通檔案
  • d 表示它是一個資料夾
  • l 表示它是一個鏈結

接下來是3組值:

  • 第一組表示檔案的擁有者的權限
  • 第二組表示檔案所屬群組中的成員的權限
  • 第三組表示其他人的權限

這些集合由3個數值組成。rwx 表示特定的身份有讀取、寫入和執行許可權。刪除的任何東西都將用 - 來代替,它允許您組合不同的數值和相對權限: rw-,r--,r-x 等.

您可以使用chmod指令更改賦予檔案的權限。

chmod可以使用兩種方式。首先是使用符號參數,其次是使用數字參數,我們先從比較直觀的符號參數開始。

您輸入chmod之後加入一個空格和一個字母:

  • a 代表全部(all)
  • u 代表使用者(user)
  • g 代表群組(group)
  • o 代表其他人(others)

接著您輸入+- 來新增/刪除權限。然後輸入一個或多個權限符號(r, w, x)。

最後輸入檔案或資料夾名稱。

以下是一些例子:

chmod a+r filename #所有人現在都可以讀取
chmod a+rw filename #所有人現在都可以讀取和寫入
chmod o-rwx filename #其他人(不是檔案的所有者,不在同一個群組中的人)不能讀取、寫入或執行該檔案

您可以通過在+/-之前添加多個字母來將相同的權限應用於多個身份:

chmod og-r filename #其他人和群組不能再讀取

如果您編輯的資料夾,可以使用-r 遞歸標誌將權限應用到該資料夾中包含的每個檔案。

數字參數比較快,但我覺得它們很難記住,除非您在日常使用它們。您使用表示身份權限的數字,這個數字的最大值為7,並且它的計算方式如下:

  • 1 如果具有執行權限
  • 2 如果具有寫入權限
  • 4 如果具有讀取權限

這給我們4種組合:

  • 0 沒有權限
  • 1 可以執行
  • 2 可以寫入
  • 3 可以寫入、執行
  • 4 可以讀取
  • 5 可以讀取、執行
  • 6 可以讀取、寫入
  • 7 可以讀取、寫入、執行

我們將它們成對使用以指定所有3組權限:

chmod 777 filename
chmod 755 filename
chmod 644 filename

所有者和群組

您可以使用chown指令更改檔案的所有者:

chown <username> <filename>

您可以使用chgrp命令更改檔案所屬的群組:

chgrp <group> <filename>

管理檔案內容

less

我絕大部分時間都在使用less命令。它以漂亮且互動的界面顯示檔案內容。

使用方法:less <filename>

一旦您進入less會話,您可以通過按q退出。

您可以使用鍵來瀏覽檔案內容,也可以使用空格鍵b鍵進行分頁瀏覽。您可以通過按G跳轉到文件末尾,按g跳轉回開始。

您可以按/搜索檔案內容,並輸入要搜索的字詞。這將向前搜索。您可以使用?符號和輸入單詞來向後搜索。

該命令僅可視化檔案的內容。通過按 v 鍵,您可以直接打開編輯器。它將使用系統編輯器,在大多數情況下是 vim

按下F鍵進入跟隨模式,或即時模式。當檔案被其他程序更改時,如使用其他程序更改檔案時,您可以實時查看更改的檔案。默認情況下,這不會發生,您只會看到您打開它時的檔案版本。您需要按 ctrl-C 退出此模式。在這種情況下,行為類似於運行tail -f <filename>命令。

您可以打開多個檔案,並使用:n (切換到下一個檔案)和:p (切換到前一個檔案)進行瀏覽。

tail

我剛才在前一個指令中提到了 tail,所以讓我們利用這個機會來解釋它是什麼。

在我看來,它最好的使用情況是使用 -f 選項時。它打開檔案在最後一行,並且監視檔案內的變化。每次檔案中有新內容時,都會將其打印到窗口中。這在監視日誌檔案時非常有用,例如:

tail -f /var/log/system.log

要退出,按ctrl-C

您可以打印出檔案中的最後10行:

tail -n 10 <filename>

可以使用 + 後跟行號來打印從特定行開始的整個檔案內容:

tail -n +10 <filename>

tai 創建的功能還有更多,建議您查閱 man tail

cat

有點類似於tail,但cat還可以向檔案中添加內容,這使其非常強大。

在最簡單的用法中, cat將檔案的內容打印到標準輸出:

cat file

您可以列印多個檔案的內容:

cat file1 file2

並使用輸出重定向操作符>將多個檔案的內容串連到一個新的檔案中:

cat file1 file2 > file3

使用>>,您可以將多個檔案的內容附加到一個新的檔案中,如果檔案不存在,則創建該檔案:

cat file1 file2 >> file3

查看原始碼時,如果能打印行號就很好,您可以使用-n選項讓cat打印行號:

cat -n file1

您只能使用-b在非空行上添加行號,或者也可以使用-s來刪除多個空行。

cat通常與管道操作符 | 搭配使用,將檔案的內容作為輸入傳給其他指令:cat file1 | anothercommand

wc

wc 代表 word count (字個數)。這是最常見的使用場景:

  • wc -l file1 计算行數
  • wc -w file1 计算字數
  • wc -c file1 计算字符數
  • wc -m file1 用多字节支持字符,例如任务字符數(例如, 表示為一個字符而不是多個字符)

您可以在多個檔案上運行 wc,在這種情況下它將單獨對每個檔案進行計算,然後打印總數:

find

find指令用於根據特定的搜索模式尋找符合條件的檔案或資料夾。它遞迴搜索。

讓我們通過例子來學習它。

查找當前資料夾下樹內具有.js 副檔名的所有檔案,並打印出每個匹配檔案的相對路徑:

find . -name '*.js'

使用引號將特殊符號(*)包圍起來,以避免shell進行解析。

查找當前樹下名稱為src的資料夾:

find . -type d -name src

使用-type f只搜索檔案,使用-type l只搜索符號鏈結。

-name是區分大小寫的。 使用-iname進行大小寫不區分搜索。

您可以在多個根目錄下進行搜索:

find folder1 folder2 -name filename.txt

查找當前樹下名稱為node_modulespublic的資料夾:

find . -type d -name 'node_modules' -or -name 'public'

您還可以使用-not -path來排除路徑:

find . -type d -name '*.md' -not -path 'node_modules/*'

您可以搜索文件中包含超過100個字符(字節)的檔案:

find . -type f -size +100c

搜索大於100KB但小於1MB的檔案:

find . -type f -size +100k -size -1M

搜索超過3天沒修改的檔案:

find . -type f -mtime +3

搜索在過去24小時內修改的檔案:

find . -type f -mtime -1

您可以通過添加-delete選項來刪除匹配搜索條件的所有檔案。以下示例將刪除在過去24小時內編輯的所有檔案:

find . -type f -mtime -1 -delete

您可以對搜索結果中的每個項目執行一個命令。例如,我們運行cat來打印檔案內容:

find . -type f -exec cat {} \;

注意結束的\;{}會在執行時填充為檔案名稱。