嗨!歡迎回到上班族的命令列生存手冊。還記得最前面幾章介紹的 Standard Input 和 Standard Output 嗎?本章還會用到這個觀念,首先來看 cat
這個指令,現在我們知道 cat
從 Standard Input (也就是你的鍵盤輸入)接收 input,然後印到畫面上。
現在來印一個文字檔案,像這個 original.txt
。
$ cat original.txt
現在我們知道 original.txt
作為 standard input 被塞到 cat 裡頭了。這邊其實是 cat
幫你下了這個指令:
$ cat 0< original.txt
再複習,0 的意思是 Standard Input。有兩種輸出,1 則是 Standard Output,2 是 Standard Error。在 POSIX 系統之中,東西都是檔案,被掛在檔案系統之中,Standard Input、Output 和 Error 也都是檔案!(我知道,很酷)。
它們住在哪裡呢?他們住在 dev
目錄下面,你可以這樣查看他們的存在:
$ ls /dev | grep std
回到 cat
的例子,它還需要幫忙把結果輸出到畫面上,也就是 Standard output,完整的指令是這樣:
$ cat 0< original.txt 1> dev/stdout
也就是 original.txt
作為 standard input (編號 0),將 Standard output (編號 1) 輸出到 dev/stdout
就是畫面上。cat
都幫我們處理好了,不用打這麼多字。(黑貓、白貓、會印字的都是⋯)
還記得在講到 cat
那一章有提到 cat
本意是 Concatenate (連接) 的縮寫,然後教大家怎麼把一個合法來源的小說拼回去嗎?
那個範例是有一個小說檔案被切割成 xaa.txt
、xab.txt
、xac.txt
和 xad.txt
,然後這樣子拼回去:
$ cat xaa.txt xab.txt xac.txt xad.txt > output.txt
看到那個我們當初說先「略過」的箭頭了嗎?本來 output 是去 Standard Output,用 >
就可以調整他輸出的方式!
前面在說明不要隨便執行網路上找到的安裝 Script,以 zsh 的 Framework zsh for human 的安裝 Script 為範例,可以用上面學到的方式把它下載成一個檔案,還記得 curl
會把資料都印到畫面上嗎?只需要把他轉移到一個新檔案裡頭即可(而且要不要打副檔名隨意)。
curl -fsSL https://raw.githubusercontent.com/romkatv/zsh4humans/v5/install > install.sh
再 $ ls
就會看到多出一個 install.sh
檔案,可以試著 cat
他來看看內容。
echo
指令可以把 input 輸出到畫面上,讀者可以試試隨意 echo
一行字,例如這樣:
$ echo 你好! 你好!
這個時候,再 echo 一次,只是這次我們把輸出轉移到剛剛建立好的 install.sh
。
$ echo "好事會發生" > install.sh
再查看 install.sh
內容,發現內容完全不見了!只留下「好事會發生」!沒錯,如果用一個 >
會直接 Override(覆蓋)目標這點要特別注意!
那有辦法不要覆蓋嗎?可以!只要多打一個 >
就行了,也就是 >>
,這樣輸出就會被 Append 放置到最新的一行。一樣用上面已經被覆蓋過的 install.sh
來試試吧。
$ echo "壞事不發生" >> install.sh
再來看看目標檔案,是不是多了一行「壞事不發生」?而不是完全取代。
不過,只是改變水流流向無聲無息,能不能順便也輸出一份到畫面上阿?這就要介紹 tee
這個指令了。他可以輸出到檔案時,也同時印東西到畫面上。
這需要配合 Pipe 的使用,有沒有覺得之前學的東西全部一次出現了呢?
$ echo "好事會發生" | tee install.sh
會注意到畫面也印出了「好事會發生」,檢查一下 install.sh
也變成了「好事會發生」。看來 tee
指令預設就是 Override。
那怎麼不覆蓋呢?筆者偷偷去查了一下 tldr
指令,發現可以這樣做:
$ echo "壞事不發生" | tee --append install.sh
或者是直接簡寫成 -a
就行啦,是不是就沒有整個覆蓋了呢?
接下來的章節,一起和筆者一起來看看什麼是 Shell Script,讀者會不會想要自己寫一個呢?讓我們下一章節再見囉。