阿旺的 Linux 開竅手冊







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

 基礎篇

Chapter 4 : 檔案/目錄與路徑

4.0 Linux 的目錄與路徑
       目錄操作
       pwd 顯示工作目錄
       tree 顯示目錄樹
       cd 切換目錄
           絕對路徑
           相對路徑
       mkdir 建立目錄
           /tmp 目錄
       rmdir 移除目錄
4.1 檔案相關指令
       檔案查閱
       file 辨識檔案類型
       ls 列出檔案
       檔案類型
       Linux 的時間戳記
           atime
           ctime
           mtime
       alias 指令別名
       stat 顯示檔案屬性
4.2 查閱檔案
       cat 檔案讀取
          head 讀取檔案開頭
          tail 讀取檔案結尾
          tac 反向讀取
       od 八進制輸出
       換行(newline)
           unix2dos UNIX 轉 DOS 格式
           dos2unix DOS 轉 UNIX 格式
       echo 顯示文字
       more 可往下翻頁閱讀器
       less 可上下翻頁閱讀器
4.3 管線與重定向
       管線(pipeline)
       重定向(redirection)
           〝1>〞或〝>〞:標準輸出重定向
           〝1>>〞或〝>>〞:標準輸出累加重定向
           〝2>〞:錯誤輸出重定向
               /dev/null 無底洞
           〝2>>〞:錯誤輸出累加重定向
           〝0<〞或〝<〞:標準輸入重定向
           〝-〞:標準輸入
           〝2>&1〞或〝&>〞:stderr 重定向 stdout
           〝1>&2〞:stdout 重定向 stderr
           〝<< 字串〞:結束輸入
           tee T型管線
4.4 指令傳回值與指令執行流程
       〝&&〞傳回值為 0 執行
       〝||〞傳回值為 ≠0 執行





















檔案/目錄與路徑

4.0 目錄與路徑

目錄操作
雖然 Linux 沒有如 Windows 的 C/D/E 碟的概念,但對目錄(資料夾)的觀念是蠻類似的。(當然是 Windows〝參考〞自 UNIX,因 UNIX 出道比較早)在 Linux 文字界面下的目錄操作,只要搞定〝絕對路徑〞和〝相對路徑〞其餘都和 WIndows 下的目錄(資料夾)觀念類似,應不難了解。

文字界面下的目錄表示法為〝/www/xxx/yyy/zzz/...〞,此表示目錄法又叫〝路徑〞。如目前所在的目錄為〝xxx〞,目前所在的目錄稱〝工作目錄〞,〝xxx〞的上一層目錄為〝www〞稱〝父目錄〞,而 〝xxx〞的下一層目錄為〝yyy〞稱〝子目錄〞。父目錄和子目錄之間以〝/〞分隔,父目錄和子目錄為相對的名稱,最左邊也就是最上層〝/〞,沒有父目錄了就叫〝根目錄〞。

以實例來說明,如 user 在安裝時是根據建立使用者帳號建立了〝aaa〞,〝bbb〞兩個使用者帳號,實際的目錄結構如下圖:


當用文字界面以帳號〝aaa〞登入時工作的目錄為〝/home/aaa〞(紅色圈起來的地方),其父目錄為〝home〞,而〝Desktop〞和〝Documents〞都是〝aaa〞的子目錄。

pwd 顯示工作目錄
當使用者操作 Windows 的目錄時,Windows 的檔案管理員一般會顯示工作目錄的完整路徑如〝C:\Documents and Settings\user\My Documents〞(Windows 下父目錄和子目錄間的分隔是〝\〞,故意和 UNIX/Linux 〝/〞相反,不要弄錯)。

但 Linux 的文字操作界面一般預設的環境只會顯示工作目錄不會有路徑,雲深不知處時,輸入顯示工作目錄指令 pwd (print working directory)就知道了,用法如下。
語法:pwd [-otpiton]
指令名稱/功能/命令使用者 選項 功能
pwd/
(print working directory)顯示工作目錄/
/Any
-P 如果工作的目錄為連結檔,列出真正的工作目錄,而非連結檔的目錄


例:
[aaa@localhost ~]$ cd ~ ←進入自己的家目錄
[aaa@localhost ~]$ pwd ←顯示完整的工作目錄(帳號〝aaa〞的家目錄)
/home/aaa
[aaa@localhost ~]$ cd /var/mail ←進入目錄〝/var/mail〞
[aaa@localhost mail]$ pwd ←顯示目前的目錄
/var/mail
[aaa@localhost mail]$ pwd -P ←列出真正的工作目錄(非連結檔的目錄)
/var/spool/mail
上例先用了 cd ~ 進入登入者帳號的的家目錄,由上述的實驗可知一般用戶的〝家目錄〞為〝/home/xxx〞(xxx 為用戶名稱),但 root 的〝家目錄〞為〝/root〞。如果工作的目錄為連結檔,用 pwd -P 可列出真正的工作目錄。


tree 顯示目錄樹
pwd 只能顯示工作目錄,但要顯示工作目錄下有那些子目錄或其父目錄可用指令 tree。(部分 CentOS/Redhat 可能沒收錄此工具,以系統管理員執行 yum -y install tree 來安裝)
語法:tree [-otpiton][--option] [path]
指令名稱/功能/命令使用者 選項 功能
tree/
顯示目錄/
Any
-a 展開列出所有檔案和目錄.包含以〝.〞開頭的隱藏檔
-C 使用彩色清單(目錄和檔案不同顏色)
-d 只列出目錄不列出檔案
-F 為不同的檔案類型後面加識別字元
〝/〞為目錄
〝=〞為 socket
〝*〞為執行檔
〝|〞為 FIFO
-g 列出所屬的群組
-p 列出權限
-u 列出擁有者
-I pattern 不列出符合 PATTERN+萬用字元組合的檔案和目錄
-P pattern 列出符合 PATTERN+萬用字元組合的檔案和目錄
-l 如為目錄為連結檔,直接列出其原始目錄
-L level 只列出幾 level 的目錄階數
-x 只列出目前的檔案系統
(例如目前的 file-system 為 ext3,但有些目錄可能為 ext2 或 FAT 等會被排除)
--help 指令自帶說明

例:
$ tree -L 1 / ←列出從根目錄開始一階的目錄
/
|-- bin
|-- boot
|-- dev
|-- etc
|-- home
|-- lib
|-- lost+found
|-- media
以下略

例:
$ tree ←如沒有任何路徑,會列工作目錄下的檔案和子目錄
.
|-- Dektop
|-- Documents
|-- Download
|-- Music
|-- Pictures
|-- Public
|-- lost+found
以下略

例:
$ tree -d /home ←列出 /home 內的子目錄,且只列出目錄不列出檔案
/home
|-- aaa
|   |-- Desktop
|   |-- Documents
|   |-- Music
|   |-- Pictures
|   |-- Public
|   `-- Videos
`-- bbb [error opeing dir] ←如果權限不夠,是無法進入或列出不屬於自己權限的目錄(除非用 root 登入)

cd 切換目錄
要變更工作目錄,如果權限許可,可用〝cd [路徑]〞(change directory) 自由的變更工作目錄。

例:
[aaa@localhost ~]$ cd /bin
[aaa@localhost bin]$ ←提示符號改變了,表示已進入 /bin 目錄
[aaa@localhost bin]$ pwd ←用 pwd 指令確認一下
/bin
[aaa@localhost bin]$ cd /home/bbb ←到 bbb 的家目錄瞧瞧
-bash: cd: /home/bbb: Permission denied ←權限不夠是進不去的喔

另外 Windows 慣用的目錄或檔案名稱常用空格,目錄或檔案相關的操作如有空格時,此時要用上引號 " 或 ' 把有空格的路徑包起來。如 cd "/home/aaa/My Documents"cd '/home/aaa/My Documents'cd /home/aaa/'My Documents'(上引號只包有空格的那一目錄)。

傳統的 UNIX ,對檔案或目錄的命名是偏好用〝-〞或〝_〞來代替空格(如 My-Documents 或 My_Documents),可免去路徑加引號的麻煩,另外文字界面下的目錄操作可分〝絕對路徑〞和〝相對路徑〞。 另外 Linux 的目錄操作還有其他的表示法 : 其中〝.〞或〝./〞,〝~〞或〝~/〞〝..〞或〝../〞最後面有沒有〝/〞差在那麼呢?最主要差別為如果路徑後面要接檔案,最後面要加〝/〞,如 cp ./fileA ~/fileB ,但如路徑後面沒接檔案兩者是一樣,如 cd ~ 等於 cd~/ ,最保險的做法是不管三七二十一,最後面加〝/〞就對了。

另外〝./〞另一個用法為用在間隔,例如有人喜歡特立獨行取一些特別奇怪的檔名或目錄名,但檔名和目錄名如和選項〝-〞相沖時可用〝./〞區隔。

例:
$ mkdir ./-dir ←建立一目錄〝-dir〞
$ tree -d ←用 tree 指令驗證一下
.
|-- -dir ←剛建立的目錄〝-dir〞
|-- Dektop

以下略
$ cd ./-dir ←進入子目錄〝-dir〞
$ cd .. ←回上一層目錄
$ rmdir ./-dir ←刪除目錄〝-dir〞

上例中如檔名或目錄名以〝-〞開頭,如沒用〝./〞間隔還真的沒辦法對其操作。

mkdir:建立目錄
Linux 目錄有兩種,一為用指令 mount 把 Linux 可識別的檔案系統掛載(Mounted)為目錄,另一為用指令 mkdir 建立的目錄。mkdir make directory 建立目錄的意思,其用法如下。

語法:mkdir [-otpiton][--option] directory
指令名稱/功能/命令使用者 選項 功能
mkdir/
(make directory)建立目錄/
Any
-m 設定目錄的權限
-p 建立巢狀目錄(一次可建立好幾層的目錄)
--verbose 顯示所建立的目錄
--help 指令自帶說明

我們來實際操作 mkdir 看看,但操作之前先了解一下 UNIX/Linux 一特殊的 /temp 目錄。



rmdir 移除目錄
移除目錄指令 rmidir (remove directory),用法和建立目錄指令 mkdir 類似,但限制更多,該目錄是空的(目錄內沒檔案)才可移除,預設還要一層一層的移除。

rmidir
是很仁慈的指令〝寧可錯放,不要錯殺〞雖然另一指令 rm 也可用來殺目錄,但 rm 指令〝殺很大〞殺傷力太強,萬一打錯字很容易傷及無辜,故建議殺目錄用專屬的指令 rmdir ,用法如下。
語法:rmdir [-otpiton][--option] directory
指令名稱/功能/命令使用者 選項 功能
rmdir/
(remove directory)移除目錄/
Any
-p 移除巢狀目錄(一次可移除好幾層的目錄,但一定要目錄是空目錄)
--verbose 顯示所移除的目錄
--help 指令自帶說明


例:
$ mkdir -p --verbose /tmp/111/222/333/444 ←建立多層的目錄
$ rmdir /tmp/111 ←移除目錄 /tmp/111
$ rmdir: /tmp/111: Directory not empty ←目錄內有子目錄或檔案是不能移除的
$ rmdir /tmp/111/222/333/444 ←雖都是空目錄,也要一層一層的移除(先移除最外層)
$ rmdir /tmp/111/222/333
$ rmdir /tmp/111/222
$ rmdir /tmp/111

例:
$ rmdir dir1 dir2 dir3 ←刪除目錄 dir1,dir2,dir3
$ rmdir -p --verbose project/doc/sorce ←如是空目錄(目錄內沒檔案),可好幾層一起移除


^ back on top ^




4.1 檔案相關指令

Linux 重要哲學之一是〝一切都是檔案〞(Everything is a File) ,了解檔案的操作幾乎就掌控了 Linux ,所以學 Linux 好像也沒那麼難不是嗎?

檔案查閱
許多人在使用 Windows 時應都有如下經驗,開啟一不知類型的檔案時, Windows 還會反過來問要用那一程式來開啟(下圖)

一般來說,Windows 是根據副檔名(小數點後面的檔名)來判斷是那種檔案類型;如〝.exe〞是執行檔〝jpg〞為圖 檔〝.ini〞是設定檔等。但 Linux 下的副檔名只供〝參考〞,例如 Linux 的執行檔大部分都沒用副檔名,要判斷檔案的類型,通常用 file 指令。不知道為什麼 Windows 沒有類似 file 這麼好用的指令,看到不認識的副檔名就直接出現如下圖的畫面。



file 辨識檔案類型
指令 file 會盡可能去分析已知的檔案的類型,如 ELF(執行檔),ASCII (純文字檔),Shell Script (腳本語言),壓縮檔或圖形檔或其他五花八門的類型,是檔案格式的照妖鏡。

例:
$ file /bin/su ←看一下 /bin/su 是什麼檔
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynami
cally linked (uses shared libs), for GNU/Linux 2.6.9, stripped ←32 位元的執行檔〝ELF〞(Executable and Linkable Format,可執行和可鏈接格式)

$ file /usr/share/man/man1/gawk.1.gz
/usr/share/man/man1/gawk.1.gz: gzip compressed data, from Unix, max compression
←gzip 壓縮檔

$ file /etc/fstab
/etc/fstab: ASCII text ←ASCII 純文檔

$ file /tmp
/tmp: sticky directory ←具 Sticky bit 特殊權限的目錄

$ file /etc/grub.conf
/etc/grub.conf: symbolic link to `../boot/grub/grub.conf' ←連結檔

ls 列出檔案
Linux 指令中 ls 使用頻率應是第一名,其指令選項之多也不惶多讓(選項和次選項加起來應超過 50 個)。

ls (list)基本的功能是列出檔案,但 Linux〝一切都是檔案〞,所以 Linux 的檔案包含了太多的資訊如時間、權限擁有者、可否執行等,所以選項才會一卡車。不過也不用煩惱,常用的選項不過就那幾個,很冷門的選項要用時再用 man pagels --help 查閱。就像台北的路那麼複雜,阿旺我又嚴重路癡,但一點也沒影響日常生活,因每天走的路就那幾條,偶然可能會去陌生的地方用 GPS 就 Ok 了。

ls常用的功能和選項如下:
語法:ls [-otpiton][--option] [path/file/directory]
指令名稱/功能/命令使用者 選項 功能
ls/
(list)列出檔案/
Any
-a 列出所有檔案和目錄.包含以〝.〞開頭的隱藏檔
-A 同 -a 但不包含代表本身的目錄的 〝.〞和其父目錄〝..〞
-B 排除已備分的檔案(以〝 ~〞結尾的檔案)
-d 只列出目錄,而不列出目錄下的檔案
-F 為不同的檔案類型後面加識別字元
〝/〞為目錄
〝=〞為 socket
〝*〞為執行檔
〝|〞為 FIFO
-l (小寫 L) 列出冗長檔案資訊(包含擁有者屬性,權限,日期,大小等)
-g 同 -l 但不包含擁有者
-G 與 -l 配合,但不列出群組
-h 與 -l 配合,檔案大小用 KiB/MiB/GiB 為單位
-c 與 -l 配合,列出 ctime 時間
-u 與 -l 配合,列出 atime 時間
-t 時間排序,一般與 -l 配合使用 (預設以 mtime 排序)
-i 列出 inode 編號
-n 同 -l 但 GID/UID 用編號表示
-m 橫向列出檔案
-o 不列出群組 (同 -lG)
-p 如為目錄,以〝/〞結尾
-R 目錄內的檔案一並列出
-X 以副檔名排序列出檔案
--help 指令自帶說明
--time==ctime 同 -c
--time==atime 同 -u
--color=never 黑白畫面列出檔案

例:
$ ls ←ls 如沒任何選項,除了根據顏色,分不出目錄或檔案 (深籃色為目錄)
Desktop    Download    Pictures    Public      Videos
Documents  Music       project     Templates
[aaa@localhost ~]$ ls -p ←色肓或黑白螢幕,可用選項 -p 或 -F 來區分檔案或是目錄
Desktop/   Download/   Pictures/   Public/     Videos/
Documents/  Music/     project     Templates/

$ ls -a ←以〝.〞開頭的檔案是隱藏檔,用選項 -a 就會現形
.              Download           .ICEauthority        Templates
..             .esd_auth          .local               .tomboy
.bash_history  .gconf             .metacity            .tomboy.log
以下略

例:
 $ ls -l ←列出冗長檔案內容
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Desktop 
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Documents 
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Music 
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Pictures 
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Public 
↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑ 
檔案類型和
權限


數 


者 

組 
大小  日期 時間  檔案或目錄

例:
[aaa@localhost ~]$ ls -al ←選項 -a ,除了列出隱藏檔,還會列出此目錄和其父目錄的屬性
total 300
drwx------  1 aaa  aaa  4096 2011-08-02 11:23 .  ←顯示此目錄的權限,擁有者,群組 
drwxr-xr-x 26 root root 4096 2010-08-04 01:23 .. ←顯示父目錄的權限,擁有者,群組
-rw-------  1 aaa  aaa  5849 2011-08-02 22:20 .bash_history ←〝.〞開頭為隱藏檔
-rw-r--r--  1 aaa  aaa  5849 2007-03-10 22:20 .bash_logout 
drwxr-xr-x  2 aaa  aaa  4096 2010-08-04 01:23 Desktop

以下略

另選項〝-d〞個人也覺的很好用,因有時只想列出目錄,而非檔案。而目錄正確的寫法為目錄名最後要加〝/〞(類似 ls -p 列出的目錄),只是預設都省略,所以要表示任一目錄可用〝*/〞表示(〝*〞為萬用字元)。

例:
$ ls -d */ ←列出工作目錄內還有那些目錄
Desktop/    Download/  Pictures/ Templates/
Documents/  Music/     Public/   Videos/

$ ls -d /home/*/ ←列出 /home 目錄內還有那些目錄
/home/aaa/  /home/bbb/

$ ls -ld /home ←列出目錄的冗長資訊
drwxr-xr-x 6 root root 4096 2011-08-02 11:23 /home


檔案類型
用指令 ls -l 所列出的第一個字元為檔案類型(File types),如〝-〞或〝d〞等,因 Linux 下〝一切都是檔案〞,所以所謂的〝檔案〞也有可能是硬體的裝置。

Linux 可能的檔案類型有: Linux 的時間戳記
ls 的選項中有許多和時間有關,因 Linux 的檔案都會記錄三種時間戳記(timestamps)即 atime、ctime 和 mtime,各代表的意義如下: 下表為 Linux 的動作對時間戳記的影響:
檔案動作 影響
  atime ctime mtime
讀//執行 yes no no
權限/擁有者變更 yes yes no
內容變更 yes no yes

例:
$ ls -lc ←列出檔案的 ctime
$ ls -l --time=ctime ←同上 (ls -lc)
$ ls -ltc ←列出檔案 ctime 並依 ctime 時間排序
$ ls -lu ←列出檔案的 atime
$ ls -ltu ←列出檔案 atime 並依 atime 時間排序
$ ls -l ←列出檔案 mtime
$ ls -lt ←列出檔案 mtime 並依 mtime 時間排序


alias 指令別名
ls -l 很常用,所以許多的 Linux 發行版,為了減少使用者輸入指令的時間,可用 ll (小寫的 LL) 來代替指令 ls -l,其實是利用指令別名 alias 的功能,所謂的別名,就是替指令取個綽號。如果你高興,也可將常用的指令取別名,其用法如下很容易 alias 別名=欲取代的指令

而如果只輸入 alias 後面都不接任何參數,則會列出目前有那些的指令被取了綽號。

例:
$ alias ←後面都不接任何參數,則會列出目前有那些的指令被取了別名
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

許多的 Linux 使用者可能也玩過 DOS,但常弄混那個是 DOS 指令那個是 Linux 指令,就常用 alias 把兩者指令統一。

例:
$ alias md='mkdir'
$ alias rd='rmdir'
$ alias cls='clear'
$ alias copy='cp'
$ alias del='rm'

上例中,輸入 DOS 的建立目錄指令〝md〞就等於輸入 Linux 相對應的指令 mkdir,此時輸入〝md〞或〝mkdir〞兩者都可接受且功能也一樣。

比較麻煩的例子為有選項時,例如 alias rmdir='rmdir -p',但如想單純的執行 rmdir 但後面不要有選項〝-p〞怎麼辦呢?只要在指令之前加反斜線〝\〞就可暫時除去別名,如 \rmdir

如要永久消除別名有一相對應的指令 unalias,用法為 unalias [-a] [別名],其中選項〝-a〞為去除所有別名 。

例:
$ unalias md ←消除 md 別名
$ unalias -a ←消除所有別名

alias 命名的別名,登出時就會消失,所以可以把常用的別名寫到家目錄的檔案〝~/.bashrc〞,此檔很類似 DOS 的〝Autoexec.bat〞(自動執行批次檔)登入時會自動執行。


stat 顯示檔案屬性
ls 功能強大資訊太多不一定方便,如只想查看檔案的各屬性,用指令 stat (file status) 是簡單又方便,stat 實際上是直接解讀 inode 的內容。

例:
$ stat /etc/fstab
  File: `/etc/fstab'
  Size: 532             Blocks: 16         IO Block: 4096   regular file
Device: 802h/2050d      Inode: 846151      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2011-08-11 01:22:13.000000000 +0800 ←atime
Modify: 2011-08-03 23:52:41.000000000 +0800 ←mtime
Change: 2011-08-04 00:52:16.000000000 +0800 ←ctime

stat 用來顯示 atmie/mtime/ctime 很方便外還包含檔案大小, 檔案類型,Inode 的編號,連結檔數等重要的資訊。

^ back on top ^




4.2 查閱檔案
cat 檔案讀取
UNIX/Linux 特別注重〝純文字檔〞(Text file)即用 ASCII 所編碼的檔案,原因是任何作業系統或平台都可讀取,所以設定檔(/etc 內的檔案)大部份都用純文字檔來儲存。連遇要加密的檔案也用純文字檔來〝明碼編暗碼〞(如 /etc/shadow),最時常來讀取純文字檔的指令就是 cat (concatenate)了。

用法如下:
語法:cat [-otpiton][--option] file
指令名稱/功能/命令使用者 選項 功能
cat/
(concatenate)檔案讀取/
Any
-A 同 -vET
-b 非空白列加行號
-e 同 -vE
-E 把〝LF〞(ASCII = 0AHEX) 顯示為〝$〞(Linux 的換行以〝$〞顯示)
-n 加行號
-s 連續多個空白列,只列一列
-t 同 -vT
-T 水平定位〝TAB〞(ASCII = 09HEX) 以〝^I〞顯示
-v 除了〝LF〞(Line Feed) 和〝TAB〞,其餘控制碼以〝^〞顯示,而 ASCII 碼 > 7FHEX 以〝M-〞顯示
--help 指令自帶說明

在實際舉例之前,先了解一下 ASCII 所謂的〝控制字元〞(ASCII # 0~31), 以 Windows 的〝記事本〞(Notepad)來說明;
在〝記事本〞中輸入一個Tab ⇌(ASCII=09HEX),是顯示 7 個空格(space),雖其顯示結果和用鍵盤輸入 7 個空格是一樣,但意義是完全不一樣;因每一種應用軟體對 ASCII =09HEX解讀不一

所以 ASCII所謂的〝控制字元〞主要用來控制輸出的結果,如換行、定位、退格等,但並不一定會有字元顯示在螢幕上,且不同的應用軟體對控制字元解讀不一。

大部分的情形,查看檔案內容時 cat 後面都不用加任何選項的,加選項可能只是要了解文字檔內容那些是真正的空格,那些是控制字元所產生的結果。另一用途為有時不同平台或應用軟體所儲存的檔案其所定義的〝控制字元〞可能和 Linux 的 tty(終端機)控制字元相沖,而使螢幕變亂碼 (如指令 reset 範例),加選項可強制用特殊符號來顯示控制字元,來避開相沖所產生的亂碼。

例:
$ cat /etc/hosts.allow ←讀取檔案 /etc/hosts.allow
#
# hosts.allow   This file contains access rules which are used to
#               allow or deny connections to network services that
#               either use the tcp_wrappers library or that have been
#               started through a tcp_wrappers-enabled xinetd.
#
#               See 'man 5 hosts_options' and 'man 5 hosts_access'
#               for information on rule syntax.
#               See 'man tcpd' for information on tcp_wrappers
#
$ cat -TE /etc/hosts.allow ←〝TAB〞(ASCII = 09HEX) 以〝^I〞顯示,
且〝LF〞(ASCII = 0AHEX) 顯示〝$〞

#$
# hosts.allow^IThis file contains access rules which are used to$
#^I^Iallow or deny connections to network services that$
#^I^Ieither use the tcp_wrappers library or that have been$
#^I^Istarted through a tcp_wrappers-enabled xinetd.$
#$
以下略

除了用 cat 讀取文字檔外還有如下三個小老弟,用在比較特殊的場合。 od 八進制輸出
cat 只能讀取文字檔,如要讀非文字檔(如執行檔),就用 od (octal dump)吧! od 指令對程式開發人員是一利器,但一般的使用者,用到的機會應不多,知道有這回事即可。

語法:od [-otpiton][--option] file
指令名稱/功能/命令使用者 選項 功能
od/
(octal dump)八進制輸出/
Any
-A[doxn] 最左邊位址顯示的方式,可接的選項有:
〝d〞為十進制
〝o〞為八進制
〝x〞為十六進制
〝n〞為不顯示位址
-t[cdfoux][#] 顯示格式,可接的選項有:
〝c〞ASCII 字元
〝d〞為十進制
〝f〞為浮點
〝o〞為八進制
〝u〞為無號十進制
〝x〞為十六進制
〝#〞為要幾個 byte 為一組顯示 (〝#〞為數字),預設為 8
-j# 跳過前面#個 byte (〝#〞為數字)
-N# 讀取的 byte 數(〝#〞為數字)
-w# 一列顯示多少 byte (〝#〞為數字)
-v 不省略相同的列(預設如二列相同,相同的列只顯示〝*〞)
--help 指令自帶說明

od 預設的輸出為八進制,但實用的輸出為十進制或十六進制,故實用的用法選項可能變很長。

例:
$ od -j50 -N20 -Ad -tx2 /bin/mkdir ←跳過前 50 byte,讀取 20 byte,位址以十進制顯示,且輸出格式為2個 byte 的十六進制
0000050 ←最左邊為位址顯示 001f 0006 0000 0034 0000 8034 0804 8034
0000066                 0804 0100
0000070
$ od -tc -Ax  /etc/hosts.allow ←以 ASCII 輸出,位址以十六進制顯示
000000   #  \n   #       h   o   s   t   s   .   a   l   l   o   w  \t
000010   T   h   i   s       f   i   l   e       c   o   n   t   a   i
000020   n   s       a   c   c   e   s   s       r   u   l   e   s    
000030   w   h   i   c   h       a   r   e       u   s   e   d       t
(以下略)


換行(newline)
vi 編輯一文件時輸入↵ Enter 實際上是記錄一換行字元〝LF〞好讓接下來的字元顯示在下一行,其中的〝LF〞(ASCII = 0AHEX) 如對照 ASCII 為控制字元的〝換行〞又叫〝newline〞或〝line feed〞。

大部分的工具指令或軟體,遇到用ASCII 記錄的純文字檔(text file)的換行字元會解讀為此行的結束而接下來的文字就會顯示在下一行,Unix/Linux 為了書寫和顯示方便常用〝\n〞來代表輸入換行字元,而〝$〞為輸出換行字元(如指令〝cat - E〞 或〝sed -n 'l'〞 會把換行字元用〝$〞顯示)。

例:
$ echo -e 'abc\x0a\x0adef\x0agh' ←用 UNIX 定義的 ASCII〝0A〞 來換行
abc

def
gh
$ echo -e 'abc\n\ndef\ngh' ←用〝\n〞來代表換行字元
abc

def
gh
$ echo -e 'abc\n\ndef\ngh' | cat -E ←用〝$〞來顯示換行字元
abc$
$
def$
gh$

但可不是所用平台都用一個 byte 的〝LF〞代表換行,對 DOS/Windows 來說〝換行〞是〝CR〞+〝LF〞兩個 byte 組成(微軟有點〝故意〞區別 Uniux/Linux 而用兩個 byte 來代表換行字元,浪費儲存空間)。

所以 UNIX/Linux 下的文字檔,如用 Windows 的〝記事本〞(Notepade)來開啟,因無法解讀 Linux 的換行字元,格式會跑掉。反之用 Linux 來開啟 Windows/DOS 的文字檔卻可正常的開啟( 因 Linux 對 Windows/DOS 的換行的其一 byte〝CR〞不會顯示,但另一 byte〝LF〞可正確解讀)。

不同的平台的換行字元如下: 故如有不同平台的文字檔要交流,記得要轉換其間的換行(newline)字元,才不至於格式錯亂,其轉換的指令如下。 echo 顯示文字
如果要在螢幕顯示所需的文字,最簡易的指令就是 echo,其基本的用法很簡單, echo '字串'即可。

Linux 指令如要處理字串,基本語法是用單引號『'』成對把字串括起來。雖然用雙引號『"』也可接受,甚至都沒引號也可以,但養成正確語法習慣還是很重要,因如沒用單引號『'』成對把字串括起來,有時會錯誤動作且用在 BASH shell 的時候,雙引號『"』是另有他用。

例:
$ echo 'Hello World' ←以下三種都可接受,但第一個和第二個最正統
Hello World
$ echo "Hello World"
Hello World
$ echo Hello World
Hello World

如果字串中有『'』,就要用雙引號『"』成對括起字串;反之如字串中有『"』,就要用單引號『'』成對括起字串。

例:
$ echo I'm a student ←引號『'』要成對出現,故此例是錯誤用法
>Ctrl+C ←可按 <Ctrl+D> 停止目前的運算或直到輸入另一『'』使引號成雙

$ echo "I'm a student" ←如果字串中有『'』,就要用雙引號『"』成對括起字串
I'm a student

$ echo "I'm Lovin' You" ←『'』 或 『"』 也可用寫成巢狀(Nested)
I'm Lovin' You

$ echo I saw a "saw"
I saw a saw ←輸出怪怪的 『"』 不見了,下例的用法才正統
$ echo 'I saw a "saw" ' ←養成正確語法的習慣很重要,指令如要處理字串,基本語法是用單引號 『'』 成對括起字串
I saw a "saw"

了解上述 echo 的用法應就夠一般所需,如想進階使用 echo ,例要顯示『I'm a student, I saw a "saw"..』用 echo 該怎麼寫呢?

echo 進階用法如下:
語法:echo [-otpiton][--option] string
指令名稱/功能/命令使用者 選項 功能
echo/
顯示文字/
Any
-n 字串最後不加〝換行〞(newline)
-e[ \abfntx0] 延伸顯示格式,可接的選項有:
\a 發出〝beep〞(ASCII = 07HEX )
\b〝退格〞(ASCII = 08HEX )(Backspace鍵)
\f〝換頁〞(ASCII = 0CHEX )(游標位置不變,但在下行顯示)
\n〝換行〞(ASCII = 0AHEX )(↵Enter鍵)
\t〝水平定位〞(ASCII = 09HEX)(Tab鍵)
\x## :##為十六進位的 ASCII 碼
\0### :### 八進位的 ASCII 碼 (\0 是數字的 zero)
--help 指令自帶說明
由上表可了解,用 echo -e '\x##' 直接輸入 ASCII 碼就可顯示 ASCII 任何字元。

例:
$ echo -e 'I\x27m a student, I saw a \x22saw\x22' ←『'』ASCII 碼為27HEX ,『"』ASCII 碼為 22HEX
I'm a student, I saw a "saw"

echo $'\x##' = echo -e'\x##'(##為十六進位的 ASCII 碼)。

例:
$ echo $'\x41\x42' ←列出 ASCII=41(hex)和42(hex)的子元
AB

例:(了解 echo -e 的進階用法)
$ echo -e Linux is\f a PC OS
Linux isf a PC OS ←輸出怪怪的?〝\f〞(水平定位)沒功用?有時如沒用單引號『'』成對把字串括起來,會錯誤動作
$ echo -e 'Linux is\f a PC OS' ←用單引號『'』成對把字串括起來就 Ok 了
Linux is
         a PC OS
$ echo -e 'Linux is\n a PC OS' ←利用〝換行〞即可用 echo 顯示超過一行以上的字串
Linux is
 a PC OS
$ echo -e 'Linux is\t a PC OS'
Linux is         a PC OS
$ echo -e 'Linux is\x9 a PC OS' ←直接輸入 ASCII 碼〝09HEX〞來代替〝水平定位〞
Linux is         a PC OS
$ echo -e '\xe' ←不小心用錯 ASCII 的控制碼,可能會造成亂碼哦 !
[▒▒▒@┌⎺␌▒┌␤⎺⎽├ ·]$ ←亂碼產生時,記得輸入重置螢幕指令〝reset〞

more 可往下翻頁閱讀器
cat 指令來閱讀文字檔時,如果此文字檔很大(如 cat /usr/share/dict/linux.words),輸出一閃即過根本來不及閱讀,用翻頁閱讀器 more 或其姊妹指令 less 就可慢慢的來閱讀,指令 more 其用法如下:
語法:more [-otpiton][+ option][+/ option] file
指令名稱/功能/命令使用者 選項 功能
more/
可往下翻頁閱讀/
Any
-# 〝#〞為數字,代表螢幕要顯示的列數
+# 〝#〞為數字,代表從第幾行剛始輸出
+/<string> 搜索檔案中的字串,然後由此開始輸出

進入 more 翻頁閱讀器後的操控如下:(其操作和 vi 很類似)
例:
$ more +3 /etc/services ←從第三行開始閱讀檔案〝/etc/services〞
# Network services, Internet style
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries

中間略

tcpmux          1/udp                           # TCP port service multiplexer
--More--(0%) ←目前所在的頁數佔整個檔案的百分比

less 可上下翻頁閱讀器
more 只可向下翻頁的單行道,真有點不便,所以後來又有可上下翻頁的翻頁閱讀器 less。用 less 閱讀時可壓Home / EndPage Up / Page Down來上下頁查閱。

例:
$ less FileA

less 因可上下翻頁故其用法和 more 類似但比 more 更複雜些,有興趣可在執行 less 時壓Hh進入操作說明自行參考。

^ back on top ^




4.3 管線與重定向

讓 Linux 文字界面功能有如核分裂般的強大威力,管線(pipe-line)、重定向(redirection)和萬用字元(Wildcard Characters)這三劍客功不可沒。管線和重定向可讓各別功能有限的指令產生核分裂而催化出強大的功能,。

如利用指令配合重定向如 tr -d '\r' < DOS_FILE > UNIX_FILE 就可取代指令 dos2unix ,其組合可千變萬化,是圖形操作界面所望塵莫及的。

管線(pipeline)
把某一 Linux 的指令的輸出(不含錯誤輸出)當另一指令的輸入就是〝管線〞或叫〝管道〞(pipe-line)的基本概念。〝管線〞模擬真實世界中的水管,可接住不同方向的水流再利用,所以 UNIX/Linux 的管線符號也是一水管〝|〞。

基本上 Linux 的標準輸入(stdin)為鍵盤,標準輸出(stdout)為螢幕,以指令 cat /usr/share/dict/linux.words 為例,如沒用管線基本上輸出為螢幕,就算有一目十行的能力也不可能看清輸出。故可用〝管線〞把原要輸出到螢幕的資料接到翻頁閱讀器 moreless ,最後再由 moreless 輸出到螢幕; 如 cat /usr/share/dict/linux.words | less 就可用 less 一頁頁慢慢的閱讀。

故管線的基本用法為〝某指令的 stdout | 某指令的 stdin〞,大部分有輸出到螢幕的指令都可透過管線給另一指令當輸入來源。

例:
$ ls -F /etc | grep '/$' ←列出目錄但不列出檔案(常用)
$ ls -F /etc | grep -v '/$' | less ←列出檔案但不列出目錄再經管線到 less
$ cat file | more ←輸出檔案到翻頁閱讀器
$ echo abcd | tr [:lower:] [:upper:] ←輸出經管線到 tr 改大寫輸出

管線也可用在周邊裝置,如 cat file | lpr 為用印表機列印文件。

管線如何應用,只受限於想像力,例如我要查詢某字元或字串的 ASCII 碼,就可利用指令 od 配合管線來達成。

例:(用管線把字串的 ASCII 碼列出)
$ echo -n 'Linux' | od -An -tx1 ←以十六進制列出字串〝Linux〞的 ASCII 碼
4c 69 6e 75 78

pipeline 的應用也可很複雜,理論上只要符合〝某一指令的 stdout 當另一指令的stdin〞即可無限延伸。如想知道已建立了那些的帳號,可如下例:

例:
$ cat /etc/passwd | grep '/home' | cut -d: -f1 | sort
aaa
bbb
john
austin

重定向(redirection)
〝Redirection〞中文有有人譯為〝轉向〞、〝導向〞、〝重導向〞或〝重定向〞,

管線中有稍為介紹說:「Linux 的標準輸入(stdin)為鍵盤,標準輸出(stdout)為螢幕」。
更詳細一點如下表,標準輸入 stdin 的 fd 為 0。經指令或程式處理後,如可正常處理所產生在螢幕的訊息為標準輸出 stdout (fd 1)。如處理有誤也會有錯誤輸出到螢幕即 stderr(fd 2)。
輸入   程式   輸出
fd 0,stdin (standard input) programs fd 1,stdout (standard output)
fd 2,stderr (standard error)
但輸出/入的〝標準〞是可以改的,輸出輸入是可〝重定向〞(redirection) 的不一定是鍵盤或螢幕,舉例來說一個指令或程式的輸出原本是輸往螢幕,經〝重定向〞後可輸往檔案。

管線的符號只有〝|〞比較簡單,但〝重定向〞的符號因有 stdin (fd 0), stdout (fd 1) 和 stderr (fd 2),和累加重定向,所以組合複雜一些;下為可能的表示法和用法:

符號 動作
1> 或 > 標準輸出重定向,因標準輸出(stdou)的 File Descriptor 原本就是1,故〝1〞可省略
1>> 或 >> 標準輸出累加重定向
2> 錯誤輸出(stderr)重定向
2>> 錯誤輸出累加重定向
0< 或 < 標準輸入重定向,因標準輸入(stdin)的 fd 原本就是0,故〝0〞可省略
- 標準輸入
2>&1 stderr 重定向 stdout
1>&2 或 >&2 stdout 重定向 stderr
<< STRING 結束的輸入字串

有些重定向功能有點抽象,一一來說明: tee T型管線
〝1>〞或〝>〞標準輸出重定向可把原輸往螢幕輸往檔案(或裝置檔),但如果想同時要輸往螢幕又要輸往檔案怎麼辦呢?就在管線中再加一分流管線成〝T型管線〞即可。
〝T型管線〞指令 tee 的動作如下圖,接個分流管把檔案分流出來:


T型管線 tee 用法如下:

語法: read_from_stdout | tee [-otpiton] file
指令名稱/功能/命令使用者 選項 功能
tee/
(pipe tee) T型管線/
Any
-a 輸出累加重定向
-i 忽略中斷

例:
$ echo 'Hello World' | tee tee_file.txt ←把原只輸出到螢幕用T型管線 tee 同時分流向檔案(螢幕和檔案都有輸出)
Hello World ←螢幕的輸出
]$ cat tee_file.txt ←驗證一下用 tee 分流出來的檔案
Hello World

例:
$ man tee | tee -a file1 file2 file3 ←tee 可一次分流出多個檔案


^ back on top ^




4.4 指令傳回值與指令執行流程

Linux 99% 以上用 C 語言寫的,而 C 語言有一特色就是程式結束時會傳回一值給系統。其間的共識是如程式執行無誤傳回值為 0。如非 0 表示程式執行時遇到狀況。

其傳回值有兩個功用,其一讓可知錯誤的原因 (非 0 的傳回值可查表或由 manpage 得知可能的錯誤原因)其二是給腳本語言(Script Laguage)作流程的判斷。

那如何知道指令的傳回值?在文字介面下輸入 echo $? 即可知上個指令的傳回值。

例: (以一般使用者的帳號登入測試)
$ cd ~root ←進入 root 的家目錄
bash: cd: /root: Permission denied ←許可拒絕 (有錯誤產生)
$ echo $? ←查看剛的指令傳回值
1 ←非 0 表示程式執行有誤
$ cd ~ ←進入自己的家目錄
$ echo $? ←查看剛的指令傳回值
0 ←為 0 表示程式執行正確

〝&&〞傳回值為 0 執行
當〝&&〞前面指令執行無誤(傳回值為 0時)則〝&&〞後面的指令會被執行,如否則否,時常用於腳本語言的判斷式。

基本的用法為 CMD1 && CMD2 && CMD3 && ... && CMDn,其規則是:由左自右,如指令執行結果無誤(執令傳回值為 0)即可穿越〝&&〞執行下一個指令;如執行結果有誤,會被〝&&〞擋住不執行。(其實還蠻好記的,符號〝&&〞都是洞洞,故傳回值為 0 可穿越而執行下一個指令)。

例:
# cd /root && mv /root/fileA /root/fileB && clear ←如執行〝cd〞無誤則再執行〝mv〞如再如誤誤則執行〝clear〞

〝||〞傳回值為 ≠0 執行
和〝&&〞相反,〝||〞為執行結果傳回值 ≠0 (執行結果不太正常)才執行後面的指令。

例:
$ cat /etc/man.conf || cat /etc/man.config ←如〝cat /etc/man.conf〞 有誤則執行〝cat /etc/man.config

〝&&〞和〝||〞可混搭使用。
例:
$ [ -f fileA ] && [ -f fileB ] && echo "exist" || echo "Not found" ←如第一個指令結果不正常〝&&〞後的指令都不會被執行而是執行〝||〞後面的指令


^ back on top ^











www.reliablecounter.com
digital mastering