# Linux (四) - 檔案與目錄操作 在 [Linux (二) - 檔案系統架構](https://tienyulin.github.io/linux-filesystem/) 中,我們有介紹過了幾個用來操作檔案和目錄的基本指令,`ls`、`cd`、`mkdir`。這一篇要來介紹更多常用的檔案和目錄操作指令。 <!-- more --> ## 路徑 操作檔案必須要先知道檔案的路徑才能進行存取,而存取檔案的路徑可以分為絕對路徑和相對路徑。 ### 絕對路徑 絕對路徑就是直接指定路徑,例如 : `/home/user1/test.txt`。 ### 相對路徑 相對路徑通常是用於退回到前幾層再去訪問其他的目錄,退回前一層的方式是加上 `../`。所以相對路徑看起來就會像是 `../../user1/test.txt`。 如果是要指定當前路徑則是 `.`。 ### 切換路徑 有了路徑之後就可以透過 `cd` 指令切換路徑,例如 : `cd /home/user1` 就可以切換到 `user1` 目錄下。 更多切換路徑的範例請參考 [Linux (二) - 檔案系統架構](https://tienyulin.github.io/linux-filesystem/#cd)。 ## 常用命令 以下介紹一些常用的命令,由於 [Linux (二) - 檔案系統架構](https://tienyulin.github.io/linux-filesystem/#cd) 已經介紹過 `ls`、`cd`、`mkdir` 了,這裡就不在介紹,如果你還不了解這些指令建議先去看一下。 ### pwd pwd (print work directory) 用於顯示目前所在的目錄名稱。 ```bash= $ pwd [-P] ``` `-P` 是可以選擇的參數,如果有加會列出真實的路徑,所以如果是連結檔(捷徑),就不會列出連結檔路徑而是檔案原本的位置。 **範例** ```bash= $ pwd /home/testDir ``` ### rmdir rmdir (remove directory) 用於刪除空的目錄。 ```bash= $ rmdir [-p] ``` `-p` 是可以選擇的參數,如果有加可以直接刪除上一層空的目錄。 **範例** 首先先建立兩層的目錄,接者用 `rmdir` 指定刪除第二層 `testDir`,完成後列出當前目錄會發現第一層目錄 `testDir1` 還在。所以如果希望連第一層都刪掉的話就必須加上 `-p` 參數,執行完後會發先第一層目錄 `testDir1` 已經連同第二層一起被刪掉了。 ```bash= $ mkdir testDir1 $ mkdir testDir1/testDir2 $ rmdir testDir1/testDir2 $ ls testDir1 $ mkdir testDir1/testDir2 $ rmdir -p testDir1/testDir2 $ ls ``` ### cp cp (copy) 用於複製檔案或目錄,而預設複製的檔案的權限會將擁有者設定給操作指令的使用者。 ```bash= cp [option] source|[source] [destination] ``` option : * `-a` : 會完整複製檔案,包含權限設定,如果是複製目錄則會複製目錄下所有檔案,等同 `-pdr` 三個功能。 * `-d` : 若來源檔是連結檔,則會複製連結檔屬性而不是文件本身。 * `-f` : 強制 (force) 複製,如果目標文件已經存在且無法開啟則會移除後再試一次。 * `-i` : 若目標檔已經存在則覆蓋前會先詢問。 * `-l` : 建立實體連結檔到目標檔案。 * `-p` : 連同文件屬性一起複製,非使用預設的屬性,常用於備份。 * `-r` : 遞迴持續複製,也就是會將整個目錄下的所有檔案都複製。 * `-s` : 複製成為符號連結檔 (symbolic link),就是捷徑。 * `-u` : 目標比來源舊才更新,或是目標檔不存在才複製。 **範例** 下面是一個最簡單的範例,單純將 `test1.txt` 複製到 `testDir1` 目錄下。 ```bash= $ cp test1.txt testDir1 $ ls testDir1 test1.txt ``` 下面這個範例先將 `test1.txt` 的檔案擁有者換成 `user1`,而當前的使用者是 `user2`,可以看到複製完後檔案的擁有者變成了 `user2`。 ```bash= user2@myComputer$ chown user1 test1.txt user2@myComputer$ ls -l test1.txt -rw-r--r-- 1 user1 group1 0 Sep 30 06:33 test1.txt user2@myComputer$ cp test1.txt testDir1 user2@myComputer$ ls -l testDir1 total 0 -rw-r--r-- 1 user2 group1 0 Sep 30 07:25 test1.txt ``` 接著我們加入 `-a` 和 `-f` 參數,`-a` 是為了測試加了 `-a` 之後權限是否不會被改掉,而 `-f` 則是不需要刪掉先前的檔案,可以強制覆蓋過去。可以看到最後檔案的擁有者還是維持 `user`。 ```bash= user2@myComputer$ chown user1 test1.txt user2@myComputer$ ls -l test1.txt -rw-r--r-- 1 user1 group1 0 Sep 30 06:33 test1.txt user2@myComputer$ cp -af test1.txt testDir1 user2@myComputer$ ls -l testDir1 total 0 -rw-r--r-- 1 user1 group1 0 Sep 30 07:25 test1.txt ``` 下面這個範例加入 `-i` 參數,可以看到因為檔案已經存在了,所以會先詢問是否要覆寫。 ```bash= $ cp -ai test1.txt testDir1 cp: overwrite 'testDir1/test1.txt'? ``` 接下來在來實測 `-a` 是否真的會複製目錄下所有檔案,這裡要先自行將要被複製的目錄新增多層目錄及添加檔案。可以看到原本 `testDir3` 是沒有檔案的,複製完後目錄下多了不只一層且含有檔案。 ```bash= $ mkdir testDir3 $ ls -l testDir3 total 0 $ cp -a testDir1 testDir3 $ ls -l testDir3 total 4 drwxr-xr-x 4 root root 4096 Sep 30 09:28 testDir1 $ ls -l testDir3/testDir1 total 8 -rw-r--r-- 1 tony root 0 Sep 30 06:33 test1.txt -rw-r--r-- 1 root root 0 Sep 30 09:28 test2.txt drwxr-xr-x 2 root root 4096 Sep 30 09:28 testDir2 drwxr-xr-x 2 root root 4096 Sep 30 09:28 testDir3 ``` 另外像是 `-p` 和 `-r` 其實也是可以透過組合成 `-pr` 變成 `-a`,所以如果是要完整複製一模一樣的檔案或是目錄可以直接使用 `-a` 就好。 ### rm rm (remove) 用於刪除檔案或目錄。 ```bash= rm [option] [file/folder] ``` option : * -f : 強制 (force) 刪除,不會出現警告訊息。 * -i : 互動 (interactive) 模式,刪除前會先詢問使用者。 * -r : 遞迴 (recursive) 刪除,用於刪除目錄,但也非常危險。 **範例** 首先先刪除檔案,可以看到 `-i` 其實不一定要加,預設就會在刪除前詢問是否要刪除。 ```bash= $ rm -i test1.txt rm: remove regular empty file 'test1.txt'? y ``` 接著使用 `-f` 強制刪除可以發現並不會詢問是否要刪除。 ```bash= rm -f test3.txt ``` 最後來測試刪除資料夾,可以發現直接刪除是會失敗的,所以如果是刪除資料夾一定要加 `-r`。 ```bash= $ rm -i testDir1 rm: cannot remove 'testDir1': Is a directory $ rm -r testDir1 rm: descend into directory 'testDir1'? y rm: descend into directory 'testDir1/testDir2'? y rm: remove regular empty file 'testDir1/testDir2/test1.txt'? y rm: remove directory 'testDir1/testDir2'? y rm: remove regular empty file 'testDir1/test2.txt'? y rm: descend into directory 'testDir1/testDir3'? y rm: remove regular empty file 'testDir1/testDir3/test3.txt'? y rm: remove directory 'testDir1/testDir3'? y rm: remove regular empty file 'testDir1/test1.txt'? y rm: remove directory 'testDir1'? y ``` ### mv mv (move) 用於移動檔案或目錄,也可以用來修改名稱。 ```bash= mv [option] [source] [destination] mv [option] source|[source] [directory] ``` option : * -f : 強制 (force) 覆蓋,如果目標 (destination) 檔案已經存在會直接覆蓋不會詢問。 * -i : 互動 (interactive) 模式,如果目標檔案已經存在,會先詢問是否覆蓋。 * -u : 更新 (update) 檔案,如果目標檔案已經存在且來源 (source) 檔案比較新才會更新。 **範例** 首先先建立一些測試用的檔案和資料夾,這個範例我們先測試使用 `-f` 參數,可以看到在不經詢問下 `testmv` 最後順利移動到了 `mvDirTest1` 資料夾中。 ```bash= $ touch testmv testmv2 $ ls testmv testmv2 $ mkdir mvDirTest1 mvDirTest2 $ ls mvDirTest1 mvDirTest2 testmv testmv2 $ mv -f testmv mvDirTest1 $ ls mvDirTest1 testmv ``` 接著為了測試 `-i` 參數的詢問是否覆蓋已經存在的檔案,再次新建立一個 `testmv`,並移動到 `mvDirTest1`,可以看到會在移動前詢問是否覆蓋已經存在的 `testmv`。 ```bash= $ touch testmv $ mv -i testmv mvDirTest1 mv: overwrite 'mvDirTest1/testmv'? y ``` 除了移動檔案到資料夾下,也可以移動資料夾到另一個資料夾中,如下 : ```bash= $ mv mvDirTest1 mvDirTest2 $ ls mvDirTest2 mvDirTest1 ``` mv 指令也可以重新命名檔案,概念其實就是將現有檔案移到一個新的檔案就算是重新命名,如下 : ```bash= $ mv testmv2 testmv21 $ ls mvDirTest1 mvDirTest2 testmv21 ``` ## 進階檔案操作命令 前面介紹了一些常用的檔案基本命令,下面要來介紹幾個比較進階的命令。 ### touch touch 指令可以用於新增空白檔案也可以用來更改檔案的時間戳記。但是較常用的就是用來建立空白檔案,所以更改檔案時間戳記的做法請參考 [Linux Touch命令的8種常見用法](https://ubuntuqa.com/zh-tw/article/7760.html)。 ```bash= touch file|[file] ``` **範例** touch 指令建立檔案可以一次建立多個,在先前的一些範例也都有出現過,只要指定好檔名即可。 ```bash= $ touch t1.txt t2 $ ls t1.txt t2 ``` ### cat cat (concatenate) 指令可以用於`顯示檔案內容`、`建立檔案`和`合併檔案內容`。 #### 顯示檔案內容 ```bash= cat [option] ``` option : * -A : 等於 `-vET`,可以列出一些特殊字元而不是空白而已。 * -b : 列出行號,空白行不標行號。 * -E : 將結尾的段行 `$` 顯示出來 * -n : 列出行號,包含空白行也有行號。 * -T : 將 `tab` 以 `^I` 顯示。 * -v : 列出一些看不出的特殊字元。 **範例** 加上 `-b` 參數,可以看到只有非空行會顯示行數。 ```bash= $ cat -b testcat 1 This is a test. 2 this is a test. 3 This is a tab test. ``` 加上 `-n` 參數,可以看到每一行都會顯示行數。 ```bash= $ cat -n testcat 1 This is a test. 2 3 this is a test. 4 5 This is a tab test. 6 ``` 加上 `-E` 參數,可以看到每一行都會有 `$` 符號代表換行。 ```bash= $ cat -E testcat This is a test.$ $ this is a test.$ $ This is a tab test.$ $ ``` 加上 `-T` 參數,可以看到 This is a`^I`tab`^I`test. 這行被加上了 `^I` 代表那一格是 `tab`。 ```bash= $ cat -T testcat This is a test. this is a test. This is a^Itab^Itest. ``` #### 建立檔案 cat 指令建立檔案和 `touch` 不同的是 cat 在建立時可以直接輸入檔案內容而 touch 只會建立空檔案,需要在建完後再開啟檔案編輯。如果用 `cat >` 對一個已經存在的檔案下命令的話會直接將舊的內容覆蓋掉,這點要特別注意。 ```bash= cat > [file] ``` **範例** 直接建立一個檔案並輸入內容,最後輸入 Ctrl+D 結束輸入。輸入完後可以再用 `cat` 指令列出來看,如下 : ```bash= $ cat > file1 this is file1. hello world! [Ctrl+D] $ cat file1 this is file1. hello world! ``` #### 合併檔案內容 cat 指令也可以用於合併多個檔案的內容。 ```bash= cat [file]... > [NewFile] ``` **範例** 下面這個範例可以看到最後新的 `textfile3` 將 `textfile1` 和 `textfile2` 的內容合併在了一起。 ```bash= $ cat textfile1 this is file1 $ cat textfile2 this is file2 $ cat textfile1 textfile2 > textfile3 $ cat textfile3 this is file1 this is file2 ``` ### 加入內容到檔案後面 前面提到 `cat >` 可以用來建立檔案並且直接輸入內容,而如果是要加資料到檔案的後面可以直接使用 `cat >>` 來加入。 ```bash= cat >> [file] ``` **範例** 下面這個範例可以看到先建立了一個 file.csv 的檔案,並且輸入內容。接著再用 `cat >>` 輸入一筆內容,最後輸出資料就多了一筆新增的內容。 ```bash= $ cat > file.csv id,name,sex 1,frank,male 2,simon,male $ cat file.csv id,name,sex 1,frank,male 2,simon,male $ cat >> file.csv 3,mary,female $ cat file.csv id,name,sex 1,frank,male 2,simon,male 3,mary,female ``` ### more more 指令可以用於檔案內容大於螢幕輸出視窗時,不會一次顯示全部內容導致看不到前面的內容。而是先顯示部分內容,再透過操作繼續顯示後面的內容。 ```bash= more [file] ``` 在 more 指令執行的過程中可以使用以下幾個按鍵操作 : * Enter : 向下翻一行。 * Space : 空白鍵代表向下翻一頁。 * / : 斜線後加上字串可以向下搜尋,例如 : `/net` 是在搜尋 `net` 這個字串。 * b : 往回翻頁。 * q : 立刻離開 more。 **範例** 下面的範例可以看到最後一行的 `--More--(26%)`,這是代表目前顯示的內容量,游標也會在此,所以就可以透過 `Enter`、`Space` 等等的按鍵進行操作。 ```bash= $ more anaconda-post.log Loaded plugins: fastestmirror, ovl No Match for argument: dhclient No Match for argument: dhcp-common ... ---> Package python-firewall.noarch 0:0.6.3-8.el7_8.1 will be erased --> Running transaction check --More--(26%) ``` ### less less 指令可以讓檔案輸出時擁有分頁的功能,類似於 `more` 指令。但是 `more` 指令如果要往前翻只能一次翻一頁,而 `less` 指令更有彈性,可以任意的前後翻。此外還可以任意的進行搜索。 ```bash= less [file] ``` 在 less 指令執行的過程中可以使用以下幾個按鍵操作 : * Enter : 向下翻一行。 * Space : 空白鍵代表向下翻一頁。 * / : 斜線後加上字串可以向下搜尋,例如 : `/net` 是在搜尋 `net` 這個字串。 * pagedown : 向上翻一頁。 * pageup : 向下翻一頁。 * q : 立刻離開 more。 **範例** 下面這個範例可以很明顯看到沒有像 `more` 指令一樣最後一行會有 `--More--(26%)`,而且在輸出上會快很多,因為 `more` 是一次載入完才顯示而 `less` 是要看的時候才載入。 ```bash= $ less anaconda-post.log Loaded plugins: fastestmirror, ovl No Match for argument: dhclient No Match for argument: dhcp-common ... ---> Package python-firewall.noarch 0:0.6.3-8.el7_8.1 will be erased --> Running transaction check : ``` ### vi vi 是一個文字編輯器,經常用於編輯檔案的內容。 ```bash= vi [file] ``` 在執行 vi 編輯器時,可以透過以下按鍵進行操作 : * `I`、`O`、`A` : 代表要輸入 (Insert) 內容,vi 編輯器剛開啟檔案時是預覽模式不能編輯,一定要先按下 `I` 或 `O` 或 `A` 才可以開始編輯。 * `Esc` : 從輸入模式切換回預覽模式,編輯完後必須先切換回預覽模式。 * `:q` : 離開 vi 編輯器。 * `:w` : 儲存變更,將編輯過的內容寫進檔案,可以結合 `:q` 變成 `:wq`,寫入後直接離開。 * `!` : 強制執行,可以搭配 `:w` 或 `:q` 使用。 **範例** 使用 `vi` 編輯器打開檔案後會呈現出檔案的內容,此時是預覽模式不能編輯。 ```bash= $ vi textfile3 this is file1 this is file2 ~ ~ "textfile3" 2L, 28C ``` 要編輯時按下 `I` 或 `O` 或 `A` 就可以開始編輯,並且底部會出現 `-- INSERT --`。 ```bash= this is file1 this is file2 ~ ~ -- INSERT -- ``` 編輯完後要先按下 `Esc` 鍵離開編輯模式,並且輸入 `:w` 或 `:q` 等等的命令,輸入的命令會顯示在最後一行。 ```bash= this is file1 this is file2 ~ ~ :wq ``` ## Summary 本篇介紹了一些常用的檔案操作命令,透過這些命令就可以對檔案進行複製、移動、刪除、編輯等等的操作。如此就可以更方便的對這些檔案進行管理和使用了。 ## 參考 [1] [Linux 文件與目錄管理](https://www.runoob.com/linux/linux-file-content-manage.html) [2] [Linux 檔案與目錄管理 | 鳥哥](http://linux.vbird.org/linux_basic/0220filemanager.php) [3] [Linux touch命令](https://www.runoob.com/linux/linux-comm-touch.html) [4] [Linux Touch命令的8種常見用法](https://ubuntuqa.com/zh-tw/article/7760.html) [5] [Linux cat命令用法](https://www.itread01.com/p/204415.html) [6] [vim 程式編輯器 | 鳥哥](http://linux.vbird.org/linux_basic/0310vi.php) [7] [linux中的cat,more,less指令使用](https://www.itread01.com/content/1545977108.html) ###### tags: `Linux`