home products tech support contact us

 Linux 技術支援    ⇒   基礎篇    進階篇    補腦篇    指令索引    中⇒ENG
版權所有, 引用請註明出處

 檔案操作

檔案基本操作
       連結檔
           符號連結
           硬連結
       ln 建立檔案連結
       cp 檔案複製
       rm 檔案刪除
       mv 檔案搬移
       〝\〞 跳脫字元

檔案基本操作
檔案的基本操作不外乎複製、搬移、刪除、和重新命名等,但這些操作的檔案或目錄有時並非檔案本尊而是其〝分身〞;分身檔即所謂的〝連結檔〞(Linking files),所以有必要先了解〝連結檔〞。

連結檔
連結檔有點類似 Windows 的〝捷徑〞(Shortcut),但不完全相同 ,Windows 中的〝捷徑〞是一個實際會佔空間的檔案,副檔名為〝lnk〞。捷徑檔〝.lnk〞不直接記錄內容而是記錄某檔案的路徑,其目的是可大幅節省儲存空間。例如某一檔案或目錄有 1G,但其捷徑檔〝lnk〞的大小應都小於 0.5K ,因捷徑檔〝lnk〞只記錄來源檔案的路徑和其他屬性(如是執行檔,其屬性可能還有執行時的啟動參數和啟動位置等內容)。

Linux 的檔案系統(Filesystem)標準為 ext2 / ext3/ext4,其 filesystem 檔案的資訊記錄在 inode 而內容記錄在 block 內, 而連結檔可用 inode 來記錄來源檔的路徑不一定會動用到 block ,所以 Linux 的連結檔不一不定會像 Winodws 的〝捷徑〞一般會佔實際的空間。

Linux 的連結檔有兩種,一叫〝符號連結〞另一是〝硬連結〞,差別如下。

^ back on top ^

ln 建立檔案連結
知道了連結檔,來實際觀察和練習一下,建立檔案連結指令 ln (link)用法如下:

語法:ln [-otpiton][--option] source target_link_file
指令名稱/功能/命令使用者 選項 功能
ln/
(link)建立連結/
Any
-s 建立符號連結(Symbolic Link),如無此選項預設為硬連結 (Hard Link)
-b 如要建立的連結檔已存在,會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-f 如要建立的連結檔已存在,覆蓋舊檔
--help 指令自帶說明


例: (符號連結)
$ ls -lgGh /usr/share/dict/ ←檢查目錄 "/usr/share/dict/" 大小
-rw-r--r--. 1 4.8M May 16 2010 linux.words ←目錄大小 4.8M
$ ln -s /usr/share/dict/ s_link ←建立符號連結檔〝s_link〞連結到〝/usr/share/dict/〞
$ ls -lgGh s_link ←查看一下符號連結檔〝s_link〞的大小
lrwxrwxrwx. 1 16 Jul 12 22:25 s_link -> /usr/share/dict/ ←其符號連結只佔 16 byte

上例中.如讀或寫符號連結檔〝s_link〞就等於讀或寫來源檔〝/usr/share/dict〞,但檔案大小比來源檔小多了只有 16 byte。如果細心點可能會發現到符號連結檔的大小剛好是〝路徑的字元數〞,所以符號連結檔事實上只記錄來源檔的路徑,所以 ln 如用相對路徑就可能會有延伸的問題,我們來實驗一下。

例:(符號連結檔相對/絕對路徑實驗)
$ cd ~ ←cd 到家目錄來實驗
$ echo '12345' > source ←建立一檔案〝source〞內容為〝12345〞
$ ln -sf source s_link ←建立符號連結檔〝s_link〞連結到工作目錄內的檔案〝source〞
$ cat s_link ←驗證一下軟連結檔〝s_link〞內容和〝source〞是否相同
12345
$ mv s_link /tmp ←實驗一下將軟連結檔〝s_link〞移到目錄 /tmp 下
$ cat /tmp/s_link ←驗證一下軟連結檔〝s_link〞內容
cat: /tmp/s_link: No such file or directory ←找不到檔案

$ ln -sf ~/source s_link ←用絕對路徑再實驗上述步驟
$ mv -f s_link /tmp
$ cat /tmp/s_link ←驗證一下
12345 ←如用絕對路徑,把軟連結檔移到其他目錄就不會有問題了
$ rm ~/source ←把來源檔殺掉
$ cat /tmp/s_link ←驗證一下來源檔不見了,軟連結檔會如何?
cat: /tmp/s_link: No such file or directory ←找不到檔案了

由以上的實驗可知操作符號連結最好用絕對路徑,且符號連結的來源檔如不小心被殺掉了,就變無效連結。

符號連結的來源檔不只可連結檔案,目錄,甚至可跨越不同檔案系統哦。

例:(符號連結到目錄)
$ ln -s /etc s_link2dir ←建立符號連結檔〝s_link2dir〞連結到目錄〝/etc〞
$ ls -lgG s_link2dir ←用指令 ls 看一下〝s_link2dir〞有無連結到目錄〝/etc〞
lrwxrwxrwx 1 4 2011-09-13 16:49 s_link_dir -> /etc
$ cd s_link2dir ←看一下可不可以進入符號連結的目錄

實驗了符號連結(symbolic link),現在來實驗硬連結(hard link)。

例:
$ cp /etc/services /tmp ←複製 /etc/services 到 /tmp 目錄下準備作為實驗的來源檔
$ ln /tmp/services h_link ←建立硬連檔〝h_link〞硬連結到來源檔〝/tmp/services〞(ln 沒選項為硬連結)
$ ls -li /tmp/services h_link ←把兩個檔案列出看看
1880233 -rw-r--r-- 2 aaa aaa 362047 2011-09-13 17:09 h_link ←兩個檔案除檔名外都一樣
(上面故意用綠字 mark 為 inode 編號,紅字為 link 數)

1880233 -rw-r--r-- 2 aaa aaa 362047 2011-09-13 17:09 /tmp/services

$ rm /tmp/services ←把來源檔殺掉看看
$ ls -li h_link ←列出硬連結檔看看有無影響
1880233 -rw-r--r-- 1 aaa aaa 362047 2011-09-13 17:09 h_link ←來源檔殺掉了,不會影響硬連結檔(但 link 數變 1)
$ cat h_link ←驗證一下來源檔不見了,硬連結檔可否讀出?

一個檔案系統(以 Linux ext2/ext3 而言),不同的檔案其 inode 會有不同的編號,如果 inode 編號相同就是同一檔案。如果多一個硬連結,其 link 數會加一,如前所言硬連結檔既是本尊也是分身,所以只要其一沒被刪除,資料都安全的故安全性較佳,但命缺點為:不可連結目錄也不可跨越不同檔案系統。

^ back on top ^

cp 檔案複製
Linux 檔案複製指令 cp (copy),基礎用法很簡易,基本上為 cp 來源檔 目的檔 cp 來源檔案1 來源檔案n 目的路徑 (把一到多個檔案複製到目錄內)或 cp 來源目錄 目的目錄,進一步用法如下:

語法:cp [-otpiton][--option] source traget
指令名稱/功能/命令使用者 選項 功能
cp/
(copy)檔案複製/
Any
-a 完全複製(包含其檔案擁有者,連結,目錄,時間)同等 -dpR (常用於備份)
-b 如目的檔已存在會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-d 如來源為符號連結檔,複製後的檔也為符號連結檔
-f 如複製的檔案已存在,不詢問直接覆蓋舊檔
-i 如複製的檔案已存在,覆蓋舊檔之前會要求詢問
-l 硬連結取代複製
-p 複製檔案時連其檔案擁有者,時間戳記,權限也一併複製
-r 遞回(recursive)複製,將來源目錄下所有的檔案及子目錄一併複製
-R 同 -r
-s 符號連結取代複製
-S字串 同 -b 但可指定備份檔字尾字串
-u 更新(只複製來源檔 mtime 時間比目的檔 mtime 時間新或目的地沒有的檔案)
-v 顯示複製過程
--help 指令自帶說明

例:
$ cp file1 file2 ←將 file1 複製到 file2
$ cp /dev/null file1 ←將 file1 內容清空
$ cp /dir/file ./ ←將檔案 /dir/file 複製到工作目錄
$ cp file ../ ←將工作目錄的檔案複製到其父目錄
$ cp -r dir1/ dir2/ ←將來源目錄 dir1 下所有的檔案及子目錄一併複製到目錄 dir2 內
$ cp file1 file2 file3 dir ←如果來源檔不只一個,目的一定要為目錄,此例為將 file1~file3 複製到目錄 dir 內
$ cp -b /dir/file ./ ←如果工作目錄 file 已存在,file 會先備份為 file~ 再進行複製的動作
$ cp -S'_backuped' file1 file2 ←如果 file2 已存在,file2 會先備份為 file2_backuped 再進行複製的動作(指定備份檔字尾字串)
$ cp -auv dir1/ dir2/ ←更新目錄 dir2 (來源為 dir1)且顯示更新的過程(此例時常用於備份)
$ cp -s file1 file2 ←同等於指令 ln -s file1 file2,建立符號連結檔 file2
$ cp -l file1 file2 ←同等於指令 ln file1 file2, 建立硬連結
$ cp -i file1 file2 ←將 file1 複製為 file2 但如 file2 已存在,覆蓋舊檔之前會要求詢問

Linux 的 cp 指令有一特色,即如果權限許可,不管來源檔擁有者群組屬誰,複製過來的檔案的擁有者和群組會變操作者所有,當然其用意是讓操作者可以完全操控複製過來的檔案.如要維持原屬性,就要用 cp -acp -p

例:
$ ls -l /etc/fstab ←查看 /etc/fstab 的擁有者和群組
-rw-r--r-- 1 root root 608 2011-09-16 00:21 /etc/fstab ←擁有者,群組,兩者目前都屬〝root〞所有
$ cp /etc/fstab ./ ←複製 /etc/fstab 到工作目錄
$ ls -l fstab ←查看工作目錄檔案 fstab 的擁有者和群組
-rw-r--r-- 1 aaa aaa 608 2012-02-10 12:50 fstab ←擁有者/群組變建立者所有

上例中就算加選項 cp -p 也無法把擁有者和群組〝root〞複製過來,因其權限不足。反之如用 root 登入操作 cp -p ,因權限無限大就可把完全複製任何的擁有者和群組。

另外複製指令 cp 如來源為檔為符號連結檔,目的檔將不再是符號連結檔(而是直接複製其目的檔),如要保留目的檔也為符號連結檔就用選項 cp -d,而 cp -a 等於 cp -d -p -R 三個選項加起來的功能,即完全複製,時常用來備份檔案。

如果用 cp 於日常的備份,但檔案很大又很多,每個檔案都複製常浪費許多時間,用選項〝-u〞可節省許多的時間。因可根據 mtime 時間來判斷檔案有無更新,或有無新的檔案來判斷是否要複製。

另外建議養成好的指令操作習慣,如操作的為目錄,目錄的字尾最好加〝/〞以區別是目錄。例如將目錄 dir1 複製到目錄 dir2, 寫成 cp -r dir1 dir2 即可,但用 cp -r dir1/ dir2/ 更清楚明白操作的為目錄。事實上目錄的標準寫法後面是要加〝/〞只是大部分的人都省略,但有些應用,目錄後面非加〝/〞不可;如 ls -d */ 為列出工作目錄內還有那些目錄但不列出檔案。

^ back on top ^

rm 檔案刪除
Linux 刪除檔案指令 rm (remove),基本用法為 rm file1 file2 fileN, 進階用法如下:

語法:cp [-otpiton][--option] file/directory
指令名稱/功能/命令使用者 選項 功能
rm/
(remove)刪除檔案/
Any
-f 不詢問直接刪除檔案
-i 刪除檔案之前會要求詢問
-r 遞回(recursive)刪除,將來源目錄下所有的檔案及子目錄一併刪除
-R 同 -r
-v 顯示刪除過程
--help 指令自帶說明

rm 刪除檔案指令也可刪除目錄,如用 rm -fr dir/ 來刪除目錄連問都不問就把整個目錄都殺光。所以 rm 是很危險的指令,所以建議殺目錄用專屬的殺目錄指令 rmdir 比較安全。

例:
$ rm file ←刪除檔案 file
$ rm 'file 1' ←刪除檔案〝file 1〞(如檔名有空格要用引號括起來)
$ rm file1 file2 file3 ←刪除檔案可連殺
$ rm -ri dir/ ←刪除目錄和目錄內的所有檔案,並要求每個檔案詢問
$ rm -rf dir ←不詢問直接刪除目錄和目錄內的所有檔案
$ rm ./-10degree ←刪除檔案〝-10degree〞

最後一個例子比較要注意一下,如檔案的第一個字用比較奇怪的字元,如例子中的檔案〝-10degree〞,但〝-〞又會被誤判為選項,所以要用代表工作目錄的〝./〞來隔開,但還是不太建議檔名太標新立異。

^ back on top ^

mv 檔案搬移
檔案搬移指令 mv (move) 和檔案複製指令 cp 用法和選項和都很類似,差別只是檔案搬移 mv 會把來源的檔案殺掉。且 mv 沒有〝-r〞或〝-R〞目錄遞回的選項,因如 mv 用於搬移目錄,已包含目錄內的檔案和子目錄一起搬移,mv 用法如下。

語法:mv [-otpiton][--option] source target
指令名稱/功能/命令使用者 選項 功能
mv/
(move)檔案搬移/
Any
-b 如目的檔案已存在,會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-f 如目的檔案已存在,不詢問直接覆蓋舊檔
-i 如目的檔案已存在,覆蓋舊檔之前會要求詢問
-S字串 同 -b 但可指定備份檔字尾字串
-u 只搬移更新檔(只搬移來源檔 mtime 時間比目的檔 mtime 時間新或目的地沒有的檔案)
-v 顯示搬移過程
--help 指令自帶說明

例:
$ mv file1 file2 ←將 file1 搬移到 file2,此例同等於將 file1 更名為 file2
$ mv dir1/ dir2/ ←將目錄 dir1(包含 dir1 內所有的檔案和子目錄)搬移到 dir2,此例同等於目錄更名
$ mv -i file ../ ←將 file1 搬移到其父目錄,如目地檔存在並要求詢問
$ mv -b file dir/ ←將 file1 搬移到目錄 dir,如目地檔存在,覆蓋之前先備份(備份檔字尾加〝~〞)

第一個例子 mv file1 file2 也是 mv 主要的用法之一,用於更名。

^ back on top ^

〝\〞 跳脫字元
跳脫字元〝\〞(escape characters)用意為因語法衝突,故不得已暫時脫離某特殊字元(、/、"、{、? 等)原預設的功能或轉變功能,例如想在螢幕顯示〝I'm happy and I'm a student〞用 echo 指令寫成 echo I'm happy and I'm a student 會引起錯誤的輸出,因單引號〝'〞或雙引號〝'〞是括入字串的意思,故如要正確的輸出可加跳脫字元〝\〞使暫時脫離引號原有的功能而寫成 echo I\'m happy and I\'m a student

例:(暫時脫離某特殊字元原預設的功能)
$ echo > "fileA" ←製造個檔案〝 "fileA" 〞
$ echo > ""fileB"" ←製造個檔案〝 ""fileB"" 〞
$ ls ←確認一下
fileA      fileB ←檔案的引號不見了?
$ echo > \"fileC\" ←加跳脫字元再製造個檔案〝 "fileC" 〞看看
$ ls
fileA      fileB      "fileC" ←〝fileC〞有引號耶

$ rm \"fileC\" ←加跳脫字元才可操作語法衝突的檔案


例:(轉變功能)
echo -e 'I\x27m a student' ←加跳脫字元使轉變功能為 ASCII 碼(ASCII 碼 27HEX為單引號)
I'm a student

\ls  ←指令之前加跳脫字元代表〝除去別名〞(大部份發行版 ls 是 'ls --color=auto' 的別名,如去除別名輸出就不會五顏六色)


^ back on top ^



 


  [註]參考 http://www.farhadsaberi.com/linux_freebsd/2010/12/hard-link-soft-symbolic-links.html