命令列程式

命令列程式通常是單獨存在的程式,執行前會先在搜尋路徑中去尋找。

常見的有:

cp, date, who, w, ls, cat, wc, last, mv, mkdir, rmdir, mv, ps, top, df, du, dd
ln, sort, sed, awk, ifconfig, dmesg, hostname, dnsdomainname, chmod, chown, chgrp
cut, grep, kill, more, less, mount, nice, ping, sleep, su, tar, gzip, touch, 
uname, basename, dirname, tr, uniq, mail

以下介紹幾個簡單命令的用法

date

用途:顯示 or 設定 系統的日期和時間

用法:

  1. date

    結果顯示現在的日期時間

  2. date MMDDhhmmYY

    調整時間,格式為 月 MM 日 DD 時 hh 分 mm 年 YY

    如: date 080109252002 是將時間調為 2002/08/01 09:25

  3. date +格式

    控制日期時間的輸出格式

    如: date +'%d %H %M' 將顯示現在的 "日 時 分"

  4. 其它進一步的用法,請 man date 查閱線上文件。

who

用途:顯示現在誰登入主機

用法:

who

顯示: ols3 pts/0 Aug 1 13:54

whoami 則顯示自己的登入帳號

ls

用途:列出目錄內容

用法:

  1. ls

    結果:列出目前所在目錄的內容

  2. ls -a

    結果:列出目前所在目錄的內容,包括隱藏檔。

  3. ls -la

    結果:使用長列模式列出目前所在目錄的內容,包括隱藏檔。

  4. 其它進一步的用法,請 man ls 查閱線上文件。

cat

用途:連結檔案內容並顯示出來

用法:

  1. cat dataf1

    結果:顯示 dataf1 的檔案內容

  2. cat dataf1 dataf2

    結果:連結 dataf1, dataf1 的內容,並予顯示。

  3. cat >>urmail.txt

    kdkdkdkdkdkdkdkdkdk (Enter)

    ^D

    將 cat 拿來當作簡易編輯器。

  4. 其它進一步的用法,請 man cat 查閱線上文件。

wc

用途:計算檔案內字數或列數

用法:

  1. wc -l dataf1

    結果:顯示 dataf1 的檔案內共有幾列

  2. wc -c dataf1

    結果:顯示 dataf1 共有多少字元。

  3. wc -w dataf1

    結果:顯示 dataf1 共有多少句元。

  4. 其它進一步的用法,請 man wc 查閱線上文件。

ln

用途:鏈結檔案;ln 提供一個方便的機制,使同一個檔案可以有多個檔名

用法:

  1. ln f1 f2

    結果:將 f1 鏈結到 f2 (硬式鏈結),f2 的檔案內容和 f1 一模一樣

  2. ln -s f1 f3

    結果:將 f1 鏈結到 f3 (軟式鏈結),f3 是 f1 的別名,取用 f3 時,實際上是存取 f1

  3. ln -sf f1 f3

    結果:同上,唯若 f3 早已存的話,將被刪除後再重建一個新的

  4. 其它進一步的用法,請 man ln 查閱線上文件。

basename

用途:取得路徑名稱中最後的檔名部份

用法:

  1. basename /usr/local/bin/sftp

    結果:出現 sftp

    以下可以得到相同結果:

    baseNAME.sh

    #! /bin/sh
    # 模擬 basename 指令
    bn=${1##*/}
    echo $bn
    
    ===============
    ./baseNAME.sh /usr/local/bin/sftp
    結果為
    sftp

dirname

用途:取得路徑名稱中的目錄部份

用法:

  1. dirname /usr/local/bin/sftp

    結果:出現 /usr/local/bin

    以下可以得到相同結果:

    dirNAME.sh

    #! /bin/sh
    # 模擬 dirname 指令
    dn=${1%/*}
    echo $dn
    
    ===============
    ./dirNAME.sh /usr/local/bin/sftp
    結果為
    /usr/local/bin

sort

用途:對文字檔的列做排序

用法:

  1. sort dataf4

    結果:將 dataf4 做升冪排序

  2. sort -r dataf4

    結果:將 dataf4 做降冪排序

  3. sort -n dataf4

    結果:將 dataf4 做升冪排序,但以字串的數值大小為比較的標準

  4. sort -n +2 dataf3

    結果:跳過前二欄,以 dataf3 中的第三欄做排序,且以字串的數值大小為比較的標準

  5. sort -nr +2 -t: /etc/passwd

    結果:-t: 是說改用 : 為分隔符號,+2 是說跳過前二欄,以 /etc/passwd 中的第三欄做降序排序,且 -n 指示 sort 以字串的數值大小為比較的標準,-r 是降冪排列

  6. 其它進一步的用法,請 man sort 查閱線上文件。

uniq

用途:對已排序好的檔案刪除重覆列

用法:

  1. uniq dataf3

    結果:若重覆列並未連續擺在一起, 則不會有任何作用

  2. sort dataf3 | uniq

    結果:刪除 dataf3 檔中的重覆列

  3. sort dataf3 | uniq -d

    結果:挑出重覆列

  4. sort dataf3 | uniq -c

    結果:計算每一列的重覆數目

  5. 其它進一步的用法,請 man uniq 查閱線上文件。

cut

用途:對檔案的每一列抽出某一部份

用法:

  1. cut -c2 dataf1

    結果:抽出 dataf1 中每一列的第 2 個字元

  2. cut -c3-10 dataf1

    結果:抽出 dataf1 中每一列的第 3 到第 10 個字元

  3. cut -c9- dataf1

    結果:抽出 dataf1 中每一列的第 9 以後的字元

  4. cut -c1-3,22- dataf1

    結果:抽出 dataf1 中每一列的第 1 到第 3 個字元、以及第 22 個以後的的字元

  5. cut -d: -f1 /etc/passwd

    結果:抽出 /etc/passwd 中的第一欄位,-d: 指示 cut 改用 : 為分隔符號,-f1 是第一欄之意

    上述指令可拿來找出所有系統的帳號名稱

  6. cut -d: -f3,4 /etc/passwd

    結果:抽出 /etc/passwd 中的第3,4欄位

  7. 其它進一步的用法,請 man cut 查閱線上文件。

paste

用途:對檔案以列和列合併

用法:

  1. paste dataf1 dataf2

    結果:dataf1 的每一列 和 dataf2 的每一列合併,預設以 TAB 分隔

  2. paste -d'#' dataf1 dataf2

    結果:dataf1 的每一列 和 dataf2 的每一列合併,以 # 分隔

  3. paste -s dataf4

    結果:dataf4 的每一列自己合併在一起 (-s : same file),預設以 TAB 分隔

  4. 其它進一步的用法,請 man paste 查閱線上文件。

tr

用途:轉換或刪除字元

用法:

  1. tr k K < dataf1

    結果:dataf1 的 k 換成 K 字元

  2. tr ',' '\n' < ttt

    結果:ttt 的 , 號換成 換行字元(\n)

  3. tr -d k

    結果:k 字元全刪除

  4. cut -d: -f1-6 /etc/passwd | tr : '+'

    結果:將 passwd 的六個欄改以 + 分隔

  5. tr '[A-Z]' '[a-z]' < dataf1

    結果:將大寫全換成小寫字母

  6. tr '[a-z]' '[A-Z]' < dataf1

    結果:將小寫全換成大寫字母

  7. tr -s ' ' ' ' < dataf1

    結果:將多餘的空白移除只剩一個 (-s 是壓擠的意思)

  8. 其它進一步的用法,請 man tr 查閱線上文件。

grep

用途:顯示符合樣式的列

用法:

  1. grep A *

    結果:將含有 A 這個字元的檔案及列顯示出來

  2. grep -i A *

    結果:將含有 A或a 這個字元的檔案及列顯示出來 (-i 是不分大小寫之意)

  3. grep -v La data3

    結果:將不含 La 的列顯示出來 (-v 是不包含之意)

  4. grep -l La *

    結果:只顯示那些檔案包含 La,不秀出符合的列

  5. grep -n La *

    結果:也秀出列號

  6. dmesg | grep eth0

    結果:將含有 eth0 的訊息列顯示出來

  7. grep -q keyword filename

    結果:若 filename 含有 keyword 則傳回 0 (真),否則傳為非 0

    命令執行完之後,它的傳回值放在 $? 這個變數中,只要 echo $? 便可得知成功與否,請記住:0 為成功,非 0 為失敗 !

練習用的資料檔

dataf1 的內容:

John   TNC    721   7654321
Marry  TCC    678   1234567
Jack   KCC    123   ABCDEFG
Bob    PTC    345   efghijk
Anne   TPC    987   1098643

dataf2 的內容:

Susan  XXX    121   1AB57RT
Jeff   AAA    478   JaBdkdk
Henry  BBB    193   LaLaLaL
Allan  DDD    621   Bobojto
Ken    JJJ    094   sssssss

dataf3 的內容:

987    XXX    121   1AB57RT
234    AAA    478   JaBdkdk
765    BBB    193   LaLaLaL
512    DDD    621   Bobojto
363    JJJ    094   sssssss
765    BBB    193   LaLaLaL

dataf4的內容:

98
2341
7
51
363

常用的特殊字元

\b      後退
\f      跳頁
\n      換行字元
\r      return
\t      TAB

一個命令列執行好幾個命令

有二種方式:

  1. 每個命令之間用 ; 號隔開

    如 ./configure ; make ; make install

  2. 每個命令之間用 && 號隔開

    如 ./configure && make && make install

問題:這二者有何差別?

&& 表示前一個命令執行成功之後,才會接著執行下一個,這樣可讓我們確保所有的命令是否都成功執行。

這經常運用在自動安裝 script 檔中,以下是我平時使用的自動安裝 Apache 及 PHP 的 script 檔:

#! /bin/sh

tar xvzf apache*.gz &&
tar xvzf php*.gz &&


echo "Configure apache ...." &&
cd apache* &&
./configure --prefix=/usr/local/apache &&
cd .. &&
cd php* &&
./configure \
          --with-apache=../apache_1.3.26 \
          --with-mysql=/home/mysql &&
make &&
make install &&
cd .. &&

cd apache* &&
./configure \
          --prefix=/usr/local/apache \
          --activate-module=src/modules/php4/libphp4.a &&
make &&
make install &&

cd ../php* &&
cp -f php.ini-dist /usr/local/lib/php.ini

註: 若一列寫不完,可在該列末尾加上接續符號 \

註: 另有 || 的用法:如 命令1 || 命令2 || 命令3

|| 是或之意,當命令1執行成功時,就不會再往下執行,若命令1執行失敗,才會執行命命2

只有當前面二個命命都執行失敗,命令3 才會被執行

也可以把數個命令弄成一組,然後整組去執行它:

第一種方法:(命令1; 命令2; 命令3; ....)

( ) 會開啟一個子 shell 環境來執行括號中的命令組

以下是把一組命令放入背景中執行:

(sort mydata -o result.txt; procdata result.txt) &

第二種方法:{ 命令1; 命令2; 命令3; .... }

不同的是,此法是把這些命令組在現行的 shell 中執行,而非在子 shell 中執行

注意 { 右方、} 左方都要有空白,每個命令都要以 ';'這個符號結束

命令列郵寄帶檔的方法

以下是將 README 這個檔案郵件帶檔寄給 ols3@www.tnc.edu.tw

#! /bin/sh

# 由命令列寄帶檔的信件

# 方法 1: 使用 uuencode 編碼

例1
uuencode README README | mail -s "test attach msg file" ols3@www.tnc.edu.tw

上述的意思是說:把 README 這個檔案(第一個 README)予以 uuencode 編碼,且將 README (第二個 README) 這個名字寫入編碼檔的檔頭,再交給 mail 寄給收信者。

例2
uuencode nc11nt.zip nc11nt.zip | mail -s "test attach msg file" ols3@www.tnc.edu.tw

# 解碼法: uudecode 編碼檔
# 或由 OutLook Express 等讀取信件的程式自動解碼。

# ------------------------------------------------------------------------------

# 方法 2: 使用 base64 編碼

uuencode -m README README | mail -s "test attach msg file" ols3@www.tnc.edu.tw

# 解碼: 
# uudecode 編碼檔
# 或
# uudecode 編碼檔 -o 指定輸出檔名
# 如 uudecode encode.txt -o nc11.zip

WinZip 也可以對 uuencode 編碼檔加以解碼,方法如下:
1. 把 uuencode 檔存為 .uue,若是 base64 編碼可存成 .b64
2. 用 WinZip 開啟編碼檔,即可按一般解壓動作來予以解碼。

=========================================================

# 註: uuencode 的用法例:

uuencode nc11nt.zip nc11nt.zip > p.txt

第一個檔名 nc11nt.zip 告訴 uuencode 要編碼的檔案是那一個,
第二個檔名 nc11nt.zip 是要 uuencode 把該檔名寫入 p.txt 表頭
它會在 p.txt 的第一列出現:
begin 600 nc11nt.zip

這樣子別人收到您的編碼檔,對方才知道您編碼之前的檔案格式為何?
因此,一般而言,uuencode 之後的二個檔名,我們都會弄成一樣。

p.txt 的內容截錄如下:

begin 600 nc11nt.zip
M4$L#!!0``@`(`.B88QW[!E;'=`<``)T2```(````9V5T;W!T+FC%5]MNXS@2
M?8X!_T-A%IA<H'0ZF;WUYLGC3M(&TG9@.]O(DT-+M$6L3'I(*IG,8/Y]3Y&4
M[#B77LS+-B*T)9'%JE.G3I5.CNBSS"MAA5=&.UH82TOIS=I_Z':(J&_63U8M
M2T\'_4,Z_?3/3QE]^HCK%-<9KI]P_94NK90T,0O_**RD2U/K(AC,:*!S6.IV
MIJ6"=55)PO]K83V9!?E2TM7PEOITK>96V*</1`/O:"6<EY:<J6T>-@Q'TV93
MM\.[^E3%'1F5YE$^2(NM4[QXOK52#]*1TG2R+$Z6NC[!KN3.SLE\RH*C<"F*
M<WHR->5"DY6%<MZJ>>WAC">ABQ-CNYV5*=3BB9\@7)S)?N'LE=L.K3%_);6T
MHJ*;>EZI'(]SJ9TDX;J=-3]RI2QH_A3VO87F.4F%]Y80KL,]G:63NIUD+R/D
M[T!X]MT2LHA5AW#XB2KA-QO?AF`3:<&PL3>E62.N$D81Z:.J*II+JIU<U%76
M[6`I?1M,OXQNI]0;WM&WWGC<&T[OSK'4EP9OD9QH2*W6E8)=1&6%]D\AF5\O
MQOTOV-#[>7`]F-ZQ_Y>#Z?!B,J'+T9AZ=-,;3P?]V^O>F&YNQS>CR04R/9&R
M09AC?Q=BIO3*`,A">J$J%X*_0VX=W*L**L6#1(YS":X4)"@'Y;^?P19R$I71
MRQ#M2SZ?DTN>!NKW1S=W@^'5A^O!S\QTA*^-S^C1*C#+FW>3'TLIH[__XV_T
......省略
M`@`(`%9^1B0K8B6N!%\``%3Q```*``````````$`(`"V@50,`0!H;V)B:70N
M='AT4$L!`A0`%``"``@`H8Y&),B0K1B*"P``<QH```H``````````0`@`+:!
D@&L!`')E861M92YT>'102P4&``````D`"0#I`0``,G<!````
`
end

==============================================================

用以下方法即可解碼回來:

uudecode p.txt -o nc11.zip