阿旺的 Linux 開竅手冊







基礎篇
進階篇
補腦篇
版權所有,引用請註明出處

 基礎篇

Chapter 7 : 檔案的壓縮/搜尋

7.0 介紹壓縮檔
7.1 常見的壓縮檔
       gz 檔
           gzip 壓縮/解壓縮 gz 檔
           gunzip 解壓縮 gz 檔
           zcat 讀取 gz 壓縮檔
       bz2 檔
           bzip2 壓縮/解壓縮 bz2 檔
           bunzip2 解壓縮 bz2 檔
           bzcat 讀取 bz2 壓縮檔
           bzip2recover 修復 bz2 壓縮檔
       Z 檔
           compress 壓縮/解壓縮 Z 檔
           uncompress 解壓縮 Z 檔
       zip 檔
           zip 壓縮檔案成 zip 檔
           unzip 解壓縮 zip 檔
           zipinfo 列出 zip 檔資訊
7.2 檔案打包
       tar 檔
           tarball 壓縮的 tar 檔
           tar 打包/還原 tar 檔
           tar 炸彈
7.3 檔案搜尋
       type 顯示指令類型
       which 尋找執行檔
       whereis 預設路徑尋找檔案
       locate 硬碟索引搜尋
           updatedb 更新硬碟索引資料庫
       find 終極檔案搜尋





















檔案的壓縮/搜尋

7.0 介紹壓縮檔

用壓縮檔的目地為減少資料的大小,就算不接觸 PC 事實上一般 user 也常常碰到壓縮檔,如用 iPod 聽 MP3 或用數位相機拍的相片檔等。但音樂的 MP3 或相片的 jpg 檔等多為〝有損壓縮〞(lossy compression),〝有損壓縮〞為將感官不易查覺的資訊捨棄,犧牲一些品質來大幅減少檔案的大小。但有些音響發燒友號稱有〝金耳朵〞可查覺 MP3 有損壓縮的失真而不屑聽 MP3 等數位音樂,同樣的許多專業的攝影也會要求不失真的 raw 檔。(raw 檔為沒處理過的原始圖檔)。

PC 的資料大多數是不容許有失真的,如你存進銀行 1000 元,總不允許變 900 元,因要求不可有任何失真,故此種壓縮稱為〝無損壓縮〞(lossless compression)。但無損壓縮因要求還原後 100% 保真,故壓縮率通常遠不如有損壓縮。

至於資料為什麼可以壓縮?舉例來說據說美國最長的地名為〝Chargoggagoggmanchauggagoggchaubunagungamaugg〞共 45 個字母。注意觀察的話會發現字母〝gg〞和〝ago〞重覆在許多地方。如想壓縮記錄此地名,我可用〝!〞代表〝gg〞用〝@〞代表〝ago〞而壓縮為〝Chargo!@!manchau!@!chaubunagungamau! 共 36 個字母就可。 user 應還可發明其他的規則可用更少的 byte 來儲存此一地名。

因要壓縮的資料規則不一,有些對文字檔的壓縮等特別有效率,有些對執行檔壓縮率較高。但對於已壓縮過的檔案不論是有損或無損的壓縮檔,強行再壓縮檔案反而可能會變大哦。也因不同的壓縮軟體對壓縮的演算法(algorithm)不一,才會有許多的壓縮軟體。


^ back on top ^



7.1 常見的壓縮檔

解鈴還需繫鈴人,用那一個軟體來壓縮就用那軟體來解壓縮,但我怎知檔案是用那種軟體來壓縮的呢?還好可根據其副檔名。一般來說 UNIX/Linux 的副檔名只供〝參考〞,例如全用 ASCII 組成的純文字檔, UNIX/Linux 不一定用〝.txt〞為副檔名,精確的判斷檔案的類型,通常用 file 指令。但UNIX/Linux 的壓縮檔卻非常倚重副檔名。

不同的壓縮指令所壓縮的檔案通常有其專屬的副檔名好讓 user 一眼便知是否為壓縮檔和那種壓縮檔。UNIX/Linux 中時常見的壓縮檔副檔名有〝.gz〞、〝.bz2〞、〝.zip〞、〝.Z〞等以自由軟體或開放源碼軟體為主流,一些有著作權的壓縮檔如〝.rar〞、〝.arj〞就盡量不用。

此外 UNIX/Linux 的世界還流行將檔案〝打包〞(Archive file),打包的目的為把許多的檔案或目錄包裝成單一檔案,好方便傳輸或保存;但打包本身並不具有壓縮的功能,為了減少體積大部分打包後的檔案會再壓縮。 最普遍的打包工具是 tar,故以〝.tar〞為副檔名,如經打包再壓縮的檔案稱 tarball,副檔名可能為〝.tgz〞、〝.tbz〞、〝.taz〞等。

gz 檔
〝.gz〞檔為 gzip 所壓縮的檔案,在 UNIX/Linux 系統中很常見。 bz2 檔
副檔名〝.bz2〞檔為 bzip2 所壓縮的檔案 ,bzip2gzip 的進階版.有更高的壓縮率而漸流行,且用法幾乎和 gzip 一樣外加有修復功能可視為 gzip 取代品。

下例同在示範 gzip 所做的動作,用 bzip2 再做一次比較一下

$ cp /usr/share/dict/linux.words ./ ←複製〝/usr/share/dict/linux.words〞到工作目錄
$ bzip2 linux.words ←用 bzip2 壓縮工作目錄檔案〝linux.words〞
$ ls -lgG /usr/share/dict/linux.words ./linux.words.bz2 ←比較壓縮前後兩檔案的大小
-rw-r--r-- 1 1711578 2011-08-04 11:01 ./linux.words.bz2 ←壓縮後只有原始檔約 1/4 大小
-rw-r--r-- 1 4953717 2007-04-02 16:49 /usr/share/dict/linux.words

$ bzip2 -d services.bz2 ←解壓縮檔案〝linux.words.bz2〞

上例測試可知 bzip2gzip 有更好的壓縮率。


Z 檔
〝.Z〞檔為 compress 所壓縮的檔案,compress 是古董級的壓縮軟體,曾很流行,但以現今的眼光來看壓縮率不高而逐漸被淘汰。許多比較新的 Linux 發行版可能不再收錄 compress 了,萬一有〝.Z〞檔要解壓縮怎麼辦呢? 不用擔心,介紹過的 gzip 可解壓縮〝.Z〞檔。可能還有不少人還在用很古老的 UNIX/Linux,故還是有必要介紹正統的 compress 指令。 zip 檔
〝.zip〞是一跨平台的壓縮格式,不但在 UNIX/Linx 中常遇到,在 DOS/Windows 和蘋果的 MacOS 或早已安樂死的 IBM OS/2 中也常見。Microsoft Windows XP 以上的版本的 Windows 還內建了 zip 的解壓縮功能,更甚者如 Htc/Samsung 的 Andoird 手機從 Google Play 下載的 App 安裝檔〝.apk〞骨子裡就是 zip 檔, zip 檔真是五湖四海。

〝.zip〞檔還有另一特色是 .gz.bz2.Z 等壓縮格式所沒有的,即〝.zip〞檔除了壓縮功能外還有打包(Archive file)的功能,也就是可把許多檔案(包含目錄)壓縮成一個檔案。



^ back on top ^




7.2 檔案打包

雖然跨平台的 zip 檔或 Windows 下流行的 rar 檔等目前主流的壓縮格式本身已直接支援壓縮和打包(Archive file)雙重功能,但正統的 UNIX/Linux 還是堅持一馬歸一馬,壓縮和打包是各自獨立的。好處是一看到檔名便知是那些檔案是壓縮檔或打包的檔案或是打包再壓縮的檔案 (tarball)。

tar 檔
〝.tar〞檔最初的目的為將多個檔案(可包含目錄)打包成一個檔案好方便備份到磁帶上,故稱〝tape archive〞即 tar 檔,tar 檔一般會用〝.tar〞作為副檔名。


^ back on top ^




7.3 檔案搜尋

Linux 的設計哲學之一是〝一切都是檔案〞,所以 Linux 的 filesystem 內的檔案是星雲密佈,故檔案的搜尋就顯的格外重要。還好 Linux 提供了檔案搜尋五虎將(typewhichwhereislocatefind)其檔案搜尋能力可是不輸〝谷歌大神〞。

type 顯示指令類型
type 嚴格來說並不是用來搜尋檔案,typeshell 內建的指令,用來顯示指令類型(如 shell 內建或是執行檔),但意外的副作用是用來尋找執行檔(指令)特別好用和簡單,用法如下:

語法:type [-otpiton] COMMAND
指令名稱/功能/命令使用者 選項 功能
type/
顯示指令類型/Any
-a 顯示執行檔(指令)可能的類型

type 優點是簡單,但缺點是只能找 shell 內建或根據環境變數 PATH 來搜索檔案[註7.3](但實際上不一定找行檔,如非執行檔的檔案放到環境變數 PATH 的路徑是可被找到)。如不在環境變數 PATH 內的檔案會找不到,另外也不能配合萬用字元來搜尋。

例:
$ type -a pwd ←看一下指令〝pwd〞放在那個目錄
pwd is a shell builtin ←〝pwd〞其一為shell 內建
pwd is /bin/pwd ←〝pwd〞其二在〝/bin/pwd〞
$ type cd ←看一下指令〝cd〞放在那個目錄
cd is a shell builtin ←shell 內建
$ type -a ls ←搜尋指令〝ls〞放在那個目錄
ls is aliased to `ls --color=tty' ←〝ls〞其一為〝ls --color=tty〞的別名
ls is /bin/ls ←〝ls〞其二在〝/bin/ls〞
$ type shadow ←搜尋文字檔〝shadow〞放在那個目錄
bash: type: shadow: not found ←type 一般用來找執行檔,或放到環境變數 PATH 內的檔案,否則會找不到

which 尋找執行檔
which 是檔案搜尋五虎將中最弱的,根本是病貓。用法幾乎和 type 一樣,但卻無 type 搜尋 shell 內建指令的功能。

例: (把 type 所舉的範例用 which 再做一次)
例:
$ which -a pwd
/bin/pwd ←which 不能找到 shell 內建指令
$ which cd
/usr/bin/which: no cd in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/
usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin) ← 在環境變數 PATH 內找不到〝cd〞(無搜尋 shell 內建指令的功能)
$ which -a ls ←搜尋指令〝ls〞
alias ls='ls --color=tty' ←〝ls〞為〝ls --color=tty〞的別名
        /bin/ls ←〝ls〞在〝/bin/ls〞
$ which shadow ←搜尋文字檔〝shadow〞
/usr/bin/which: no cd in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/
usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin) ←路徑找不到〝shadow〞

whereis 預設路徑尋找檔案
許多的書或網路上的教學都說 「 whereis 會根據資料庫來搜尋檔案,且是根據選項來找檔案類型(如執行檔等)...」應是不正確的,反正〝天下文章一大抄〞也沒去求證。

正解〝應為〞whereis 預設用來找執行檔、原始碼manpage 文件,所以不同的選項搜尋路徑會不一樣(不會用到資料庫,也不管檔案類型)。

whereis -b 為例,會搜尋〝/bin〞、〝/usr/bin〞、〝/sbin〞、〝/usr/sbin〞、〝/etc〞、〝/usr/etc〞、〝/lib〞、〝/usr/lib〞等放執行檔或二進制檔(〝*/lib〞)或設定檔(〝*/etc〞)等相關路徑。但其實並沒檢查檔案類型只要名稱符合(不管副檔名)都會列出。

whereis
用法如下:
語法:whereis [-otpiton] COMMAND
指令名稱/功能/命令使用者 選項 功能
whereis/
(where is file)
預設路徑尋找檔案/
Any
-b 搜尋執行檔的相關路徑(*/bin、*/sbin、*/etc、 */lib 等)
-m 搜尋說明檔的相關路徑(*/man 等)
-s 搜尋原始碼的相關路徑(/usr/src/*/ 等)

例:
$ whereis poweroff ←搜尋全部預設路徑(同選項〝-bms〞)名稱為〝powroff〞的檔案
poweroff: /usr/bin/poweroff /sbin/poweroff /usr/share/man/man8/poweroff.8.gz
$ whereis -m poweroff ←只搜尋放 manpage 的路徑,名稱為〝powroff〞的檔案(manpage 的路徑可由指令〝manpath〞得知
poweroff: /usr/share/man/man8/poweroff.8.gz
$ whereis -b poweroff ←只搜尋放執行檔的相關路徑,名稱為〝powroff〞的檔案
poweroff: /usr/bin/poweroff /sbin/poweroff
$ whereis shadow ←搜尋預設路徑名稱為〝shadow〞的檔案
shadow: /etc/shadow /usr/share/man/man3/shadow.3.gz .usr/share/man/mab5/shadow.5
.gz

locate 硬碟索引搜尋
因 Linux filesystem 內的檔案太多,為了加快搜尋速度所以指令 typewhichwhereis 都只搜尋各自預設的路徑。如有檔案放在家目錄〝/home/xxx〞或〝/tmp〞或自建的目錄,沒在這些指令(typewhichwhereis)預設搜尋的路徑內可會找不到檔案。locate 指令則利用索引資料庫〝/var/lib/mlocate/mlocate.db〞來搜尋檔案,搜尋的範圍更廣沒預設搜尋的路徑。 介紹完 locate 的基本知識,接下來來說明其語法。

語法:locate [-otpiton] file/directroy
指令名稱/功能/命令使用者 選項 功能
locate/
硬碟索引搜尋/
Any
-b 只列出符合〝基底檔名〞且可配合萬用字元搜尋
-n # 最多列出 # 個結果(〝#〞為數字)
-r 使用正規表示法搜尋
-i 忽略大小寫
-d 指定索引資料庫

原則上如要搜尋〝FILE_NAME〞,locate 會搜尋〝*FILE_NAME*〞,在檔名字串前後各加萬用字元〝*〞擴大列出的範圍,而列出 FILE_NAME 的部分可以是檔名或路徑或目錄。

例:
[aaa@localhost ~]$ locate 586 ←搜尋檔案字串〝586〞
locate: can not open `/var/lib/mlocate/mlocate.db': No such file or directory
↑ 如出現找不到〝mlocate.db〞可能每晚都關機,沒機會執行〝updatedb〞所產生的索引資料庫
[aaa@localhost ~]$ su - root ←請出〝root〞來手動更新〝updatedb〞
Password:
[root@localhost ~]# updatedb ←(會花一些時間產生索引資料庫)
[root@localhost ~]# locate 586 ←再搜尋〝586〞看看
/lib/modules/2.6.23.1-42.fc8/kernel/arch/i386/crypto/aes-i586.ko
/usr/lib/perl5/5.8.8/pod/perl586delta.pod
/usr/lib/rpm/i586-linux/macros ←路徑中有〝586〞也算
/usr/share/man/man1/perl5866delta.1.gz

如要排除路徑,可用 locate -b 只列出符合〝基底檔名〞(basename) 的檔案或目錄,什麼是〝基底檔名〞?,以檔案〝/var/lib/mlocate/mlocate.db〞為例,排除路徑後最右邊的〝mlocate.db〞即基底檔名。

故剛才的例子 locate 586locate -b 586 再跑一次,〝/usr/lib/rpm/i586-linux/macros〞那行就不會列出。 使用 locate -b 只列出符合〝基底檔名〞另一用處為可配合萬用字元來搜尋檔案或目錄。

例:
$ locate -b apple?? ←使用〝基底檔名〞配和萬用字元搜尋字串〝apple〞
/home/aaa/.gconf/apps/panel/applets
/usr/share/terminfo/a/apple2e
/usr/share/terminfo/a/appleII

其他選項例子如下例:
# locate -b t[!o-p]e ←使用〝基底檔名〞配和萬用字元搜尋
# locate -i x11 ←忽略大小寫
# locate -n 5 poweroff ←最多列出 5 個結果
# locate -d /var/lib/mlocate/office_hd.db file ←指定索引資料庫
# locate -r 'x\{3\}' ←使用正規表示法搜尋三個相連的〝x〞的檔案或路徑

find 終極檔案搜尋
終極檔案搜尋非 find 莫屬,除了檔名外,舉繁檔案的任何特徵如檔案大小,時間,權限,擁有者,檔案類型等都可搜尋。其哲學為:「沒有 find 找不到的檔案,除非你不會用」。

例如你硬碟快爆掉了,你想找出前 5 大最佔空間的檔案可用如下指令來找霸佔硬碟的原凶
find / -type f -exec du {} \; 2>&- | sort -n | tail -n 5

也因 find 功能強大故使用起來有點複雜,且因沒預設搜尋路徑和使用索引資料庫,而是真正把硬碟的檔案一個個翻出來找,故很花時間。

find 基本的用法為 find PATH -name 'PATTERN',如省略 PATH 則搜尋工作目錄(預設搜尋包含子目錄)。

例:(以 root 登入測試)
# find / -name 'apple??'←從根目錄開始,依樣板檔名〝apple??〞搜尋
/home/aaa/.gconf/apps/panel/applets
/root/.gconf/apps/panel/applets
/usr/share/terminfo/a/appleII
/usr/share/terminfo/a/apple2e
# find /etc /usr -name "read*" ←搜尋的路徑可以不止一個

如是一般的登入者,可能沒足夠的權限進入每層目錄去搜索而產生錯誤的輸出,故畫面會很雜亂;此時可配合錯誤輸出重定向寫成 find / -name 'aple??' 2> /dev/null ,或關掉 fd stderr 寫成 find / -name 'aple??' 2>&- 輸出畫面就乾淨多了。

find 進階用法如下:
語法:find [path] [-otpiton][--option] expression
指令名稱/功能/命令使用者 選項 功能 note
find/
終極檔案搜尋/
Any
依檔案檔名或目錄或 filesystem
-name "PATTERN" 樣板(pattern)檔名搜尋 PATTEN 可配合萬用字元樣板,但只可找基底檔名(base name)即檔案去掉路徑
-iname "PATTERN" 同 -name 但不分大小寫  
-regex "PATTERN" 正規表示法搜尋 PATTEN 支援正規表示法
-regextype 變更正規表示法所支援的種類 選項有:
〝emacs〞(預設) 、〝posix-basic〞、〝posix-egrep〞、〝posix-extended〞、〝awk〞、〝grep〞、〝egrep〞等
-iregex 同 -regex 但不分大小寫  
-path "PATTERN" 路徑樣板搜尋 和選項〝 -name〞 用法類似,但選項〝 -name〞無法對路徑符號的〝/〞或〝./〞正確匹配,用此選項可克服。

-ipath "PATTERN" 同 -path 但不分大小寫  
-prune 排除 -path 或 -ipath 指定目錄內的檔案 要配合和選項〝 -path〞使用
-maxdepth # 最大搜尋 # 層目錄(# 為數字) 如 #=1,不會搜尋子目錄
-mindepth # 最少搜尋 # 層目錄(# 為數字) 如 #=1,會搜尋任一階目錄
-fstype FILESYSTEM 指定要搜尋的 filesystem 常見的 filesystem 有
Linux 的 ext2/ext3/reiserFS
DOS 的 vfat, Windows 的 ntfs (fuseblk)
CD/DVD-ROM 的〝iso9660,DVD-ROM 的 〞udf
APPLE 的 hfs,網路的 nfs 等
-xdev 只搜尋目前的 filesystem 例如根目錄掛載了不同的 filesystem,但只找和根目錄相同的 filesystem
-mount 同 -xdev  
依檔案大小
-size [+][-]#
[bckMG]
依檔案大小搜尋,可接的項目有
〝b〞:檔案所佔的 Block(磁區),Bolock=512B
〝c〞:為 byte
〝k〞:為 1024 byte
〝M〞:為 10242 byte
〝G〞:為 10243 byte

-empty 搜尋大小為 0 的檔案或空目錄  
依檔案類型
-type [bcdpfls] 檔案類型有可接的項目有
〝b〞:區塊裝置(block device)
〝c〞:字元裝置(character device)
〝d〞:目錄(directory)
〝p〞:具名管線(named pipe)
〝f〞:正規檔(regular file)
〝l〞:符號連結檔(symbolic link)
〝s〞:socket
 
-links [+][-]# 硬連結檔 # 為連結數
-follow 排除符號連結檔  
依權限或擁有者屬性
-perm[+][-]# 依權限的數字表示法搜尋  
-user OWNER_NAME 搜尋指定擁有者的檔案  
-group GROUP_NAME 搜尋指定群組的檔案  
-uid # 搜尋檔案的 UID  
-gid # 搜尋檔案的群組 GID  
-nouser 搜尋無效擁有者的檔案  
-nogroup 搜尋無效群組的檔案  
依時間
-atime[+][-]# 搜尋 atime 時間的檔案 # 單位為天
-ctime[+][-]# 搜尋 ctime 時間的檔案 # 單位為天
-mtime[+][-]# 搜尋 mtime 時間的檔案 # 單位為天
-amin 搜尋 atime 時間的檔案 # 單位為分
-cmin 搜尋 ctime 時間的檔案 # 單位為分
-mmim 搜尋 mtime 時間的檔案 # 單位為分
-anewer ref_file 搜尋比參考檔的 atime 還新的檔案  
-cnewer ref_file 搜尋比參考檔的 ctime 還新的檔案  
-newer ref_file 搜尋比參考檔的 mtime 還新的檔案  
-daystart 搜尋從本日開始算天數的檔案 單位為天,要配合 -amin,-atime,-cmin,-ctime,-mmin,-mtime 等選項
控制/執行/輸出/其他
-print 輸出到 stdout (預設值)  
-exec 指令 {} \; 將搜尋到的結果交給後續的指令  
-ok 指令 {} \; 同 -exec 但會詢問  
-delete -把搜尋到的檔案直接刪除  
-a(and) ,-o(or) -not(!) 邏輯篩選要搜尋的檔案 ,
〝-a(and)〞同〝&&〞(傳回值為 0 執行)
〝-o(or)〞同〝||
〝-not(!)〞為邏輯的 NOT(反向)
 

find 相對複雜的用法,各舉例說明,特別要注意的為如有用到〝+〞/〝-〞符號,〝+〞表示大於其大小,反之符號〝-〞表示小於其大小,如無〝+〞/〝-〞則是剛好等於其檔案的大小。

但如用在選項〝-perm〞符號〝+〞表示邏輯的 OR,而符號〝-〞表示邏輯的 AND。(邏輯的〝OR〞其一符合就成立,而邏輯〝AND〞全部都符合才成立)

^ back on top ^











www.reliablecounter.com
digital mastering

[註73]在文字界面下輸入 echo $PATH 可查詢環境變數 PATH 在那些路徑下搜索執行檔。