- 請先下
grep $USER /etc/passwd 命令, 看看你使用的
shell 是 bash 或 tcsh. 也可以用 finger $USER 來看.
如果你用的是 bash, 就再開一個視窗, 並執行 exec tcsh
如果你用的是 tcsh, 就再開一個視窗, 並執行 exec bash
以下各個範例, 除非特別說明, 在兩個 shells 下都可以執行.
- 執行
ll $HOME/.[a-z]*
並用記事本記下印出的東西.
- 我們輸入的命令列, shell 會先對它做各種處理與代換
(substitution/ expansion)
然後才用處理過的字串來呼叫適當的命令去執行.
為了看到各種代換的效果, 我們現在就叫 shell 在處理完命令列之後,
呼叫命令之前, 先印出處理過的字串: 在 bash 視窗內下
set
-x 在 tcsh 視窗內下 set echo
- 再執行
ll $HOME/.[a-z]*
並將印出的東西與先前記事本上的比較.
使用者下的命令: ll $HOME/.[a-z]*
||
|| (經過 shell 處理)
\ /
\/
程式看到的是: ls -N --color=auto /home/ckhung/.bashrc
/home/ckhung/.cshrc ...
- 改變 shell 的提示符號: (bash 適用)
export PS1='\t \[\033[4;35m\]\h:\w\$\[\033[0m\] '
詳見 bash(1)。 可以把這句話放在 ~/.bashrc 裡面, 這樣每次開一個新的
bash, 都會執行這句。
- File name glob 的範例: 先
cd /usr/bin, 然後:
echo z* 所有 z 開頭的檔案
echo l*s 所有以 l 開頭, 以 s 結尾的檔案
echo *zip* 所有名稱中間有 zip 的檔案
echo ??zip 所有名稱長度為 5, 且以 zip 結尾的檔案
echo [A-Z]* 所有以大寫字母開頭的檔案
echo *[0-9]* 所有名稱當中至少有一個數字的檔案
請注意: 這些代換都是 shell 在做的. echo
這個命令在被呼叫起來之前, 這些特殊符號早就已經被 shell
展開成檔名了. 藉由 file name glob 的功能, 可以在沒有 ls
可以用的情況下以 echo 達到簡單的 ls 功能. (dos/windows 使用者:
dos 的 command.com 也是一個 shell, 但它並不支援這些 expansion,
所以一個應用程式想要認得命令列上的 * 與 ? 要靠它自己處理.)
- 以
echo $HOME 印出環境變數 $HOME 的值.
這是你的家目錄. 其他與目錄有關的環境變數: $PATH
命令的搜尋路徑; $MANPATH 手冊的搜尋路徑.
- 環境變數的直接應用:
cd /usr/bin 之後再
less -r $HOME/article
- 許多程式共同使用的環境變數:
$EDITOR 或
$VISUAL 你要用那個文字檔編輯器; $PAGER
你要用那個 "分頁器" (文字檔閱覽器) 來看輸出.
- 例: 在 tcsh 下
setenv PAGER head 或在 bash 下
export PAGER=head 之後再 man 1 echo Q:
如果把 PAGER 設定成 cat, 從此以後使用 man 會怎麼樣?
有沒有辦法在不把 PAGER 改回來的情況下仍舊可以讀手冊?
- 看看有那些環境變數:
setenv 或 env
(請用 which 看看這兩個命令有何不同?)
- Q: 你的環境下有幾個環境變數? Q:
有一個環境變數記載著這部機器的名稱 (例如 penguin, 或 mail, 或
digital), 是那一個?
- 命令別名範例: 先看看危險的命令 mv 的手冊,
那一個選項可以讓系統在面臨有覆蓋舊檔危險時警告你? 現在用
alias 看看目前有那些命令別名. 然後加入兩個別名 (bash
版):
alias mv='echo use mov instead'
alias mov='/bin/mv -i'
(如果是 tcsh, 則把 = 改成空格.) 再用 alias
檢查成果. 最後試著用 mv 與 mov 更改檔名. 又, 此時下 which
mv 與 which mov 得到什麼?
- alias 的應用實例: 如果你的 /etc/mailcap 設定正確的話,
文字瀏覽器 lynx 也可以用來選擇性地看圖形. 但必須把 lynx 的
-image_links 打開, 才看得到圖形的超連結; 而這只能在命令列上打開,
無法在 .lynxrc 當中設定. 所以只好在 .bashrc 當中加入
alias
lynx='/usr/bin/lynx -image_links'
- Q:
dir 命令作什麼用的?
如果不用任何代換而想造成相同的效果, 要如何下命令?
- 消除命令別名範例:
unalias mov
- 題外話:
- 看看一個二進位檔案裡面有沒有一些可以印出來看的字串:
strings /usr/bin/man
- 看看 ckhung 這個使用者發呆發了多久:
finger
ckhung 修改自己的資料, 讓別人 finger
你時看到你的姓名電話: chfn
-
Back quote (命令結果代換)
的範例
- 下
grep $(whoami) /etc/passwd 與先前的
grep $USER /etc/passwd 有相同效果.
- 看看 man 這個命令的可執行檔中, 有那些可以印出來看的字串:
strings $(which man)
- 找出 man 命令的可執行檔中, 看起來像是環境變數的字串:
strings $(which man) | grep '^[A-Z]\+$'
- 用 finger 查看目前在線上的每個使用者:
finger $(who
-q | grep -v '^#' ) 如果覺得太複雜, 可以分成兩步來做:
who -q | grep -v '^#' > a; finger $(cat
a)
xargs 命令可以把本來從 stdin
輸入的資料, 轉成後面那個命令的命令列參數. 這可以在不支援 back
quote substitution 的 shell 下做到 back quote substitution
的功能. 上述兩例可以改成: which man | xargs strings | grep
'^[A-Z]\+$' 以及 who -q | grep -v '^#' | xargs
finger
- 注:
strings $(which man)
古代的寫法是 strings `which man`
不過這種寫法無法層層相疊, 所以建議還是用前一種寫法。
- 我個人認為 pipe 與 back quote substitution
是所有命令列觀念當中, 最重要的兩項.
學會靈活使用這兩項來組合其他指令,
就可以用有限的指令產生出許多神奇的效果. 如果再配合上 regular
expression, 就可以算是半個 unix 高手了.
- 歷史代換: 先用
history
看一下你先前曾經下過那些命令.
!! 前一個命令再執行一次
!-5 倒數第五個命令再執行一次
!58 把第 58 個命令再執行一次
!wh 把最近一次下過, 以 wh 開頭的命令再執行一次
- 歷史代換也可以嵌在其他命令或代換裡面:
finger
$(!wh) 例: 從 who -q 開始, 逐次使用
!! 於下一命令中,
終至將上面命令結果代換的例子寫出.
- 避免代換的字元: ' ... ' 避免掉幾乎所有的代換; " .... "
避免掉多數代換, 但是裡面變數代換照常進行; \
避免掉它後面那個字元的特殊意義. 例如
echo \$HOME 與
echo '$HOME'
- 作業: 運用 file name glob 與避免代換的字元等等功能,
把自己家裡亂七八糟的檔案清除乾淨.
- 作業: 自己查手冊, 看看下面這兩個命令有什麼用處:
find ~ -name '*.[ch]' | zip -@ ~/backup.zip
zip ~/backup.zip $(find ~ -name '*.[ch]' )
如何把上述命令設定成 alias, 讓你將來 login 到你的帳號以後,
隨時都可以下 "savework" 命令, 而達到備份重要資料的效果? (提示:
可能需要用到 " ... " 避免 shell 在你下 alias
命令時就急著想要代換.)
- 要取消「印出 shell expansion 處理完的命令列字串」這個效果,
可以在 bash 視窗內下
set +x 在 tcsh 視窗內下
unset echo
- 要改變你所使用的 shell 可以用
chsh
但是並不是系統內有安裝的 shells 都可以用, 只有記載在 /etc/shells
內的才可以用. 如果你喜愛的 shell (例如是 pdmenu) 並未在允許的
shells 之中, 可以在 .login 或 .profile 當中寫 exec
/usr/bin/pdmenu
- 簡單的迴圈:
for i in guava pineapple cherry orange ; do
echo $i ; done
- 例如要將一片 12 軌的音樂 cd 上所有的歌曲全部變成 mp3,
可以這樣下:
for i in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
cdda2wav -D /dev/cdrom -x -q -t $i+$i - | lame -h -S - $i.mp3 ;
done 至於它到底有幾軌, 如何得知呢? cdda2wav -D
/dev/cdrom -J -v all
- 一口氣把家目錄底下 (含子目錄, 孫目錄, ...) 所有 .doc 檔轉換成
.html 檔:
for f in $(find ~ -iname '*.doc' | sed 's/\.doc//'
) ; do echo "converting $f.doc ..."; wvHtml $f.doc $(echo $f | sed
's#.*/##g').htm ; done
- 如何一次產生很多帳號? 例如要從這樣一個學生名單檔案 grade.txt 一口氣建立很多 unix 帳號, 可以這樣下:
for user in $(perl -ne 'print "$1\n" if /^(\w+):/'
grade.txt) do ; useradd -g users $user ; done