關聯問題:http://www.zhihu.com/question/20244763
如果程式設計語言是否可以作為系統Shell使用,與它的流行程度正相關,那為何Python還沒有成為標配的系統Shell?
選擇Python(或其它)作為系統Shell,一定就比Bash或者POSIX Shell更經濟嗎?
回複內容:
Shell 是有很多缺(tuo)陷(xie)的。比如說一個最簡單的例子,如果你下載的檔案名稱字裡面有很多空格,在準備大量操作比如歸檔的時候都會很麻煩。Shell 的自動解析通常會把你搞得很慘。而且那東西還是個feature 對吧?那不是bug。
其實這就是很典型的不適合用Shell去解的問題嘛。你找個沒有自動解析的工具,比如說隨便哪種指令碼語言都行啦。為什麼選Ruby呢?當然因為Ruby有 irb 咯。
irb(main):033:0> dir = 'Archive-Dir'
irb(main):034:0> dst = 'Your-destination-directory'
irb(main):035:0> num = 16
irb(main):036:0> lines = `ls -rt ~/Downloads/ | tail -n #{num}`.split("\n")
irb(main):037:0> lines.each { |l| print `mv "#{l}" #{dir}/#{dst}` }
這樣一來就是這麼簡單了,其實就只有兩行嘛。我只所以寫那麼多變數是因為我還有很多檔案需要互動的去做的。那麼我就只需要改變數,然後用箭頭找曆史,一路斷行符號就行了。
但是為什麼 Shell 還是不能夠被取代呢?因為還有大量的互動式任務用 Shell 的時候可以簡單到不可想象的地步。
diff -u <(ls | sort ) <( grep amazon mp3.url.txt | \
awk -F '/' '{print $NF}' | sort ) 2>&1 | \
egrep '^\+[^+]' |sed -e 's/^\+//' | \
xargs -n 1 ./download.sh
甚至於是這樣
diff -u <(ls | sort ) <( ssh -i ~/my.key dove@myhost grep amazon mp3.url.txt | \
awk -F '/' '{print $NF}' | sort ) 2>&1 | \
egrep '^\+[^+]' |sed -e 's/^\+//' | \
xargs -n 1 ./download.sh
所以呢,應該用 Shell 處理的問題還是要用 Shell 處理的。
順便問一下,為什麼不用 Python ?
我真的不想僅僅因為沒對齊…… …… ……
人生苦短,不用Python。
稍微補充一點 Shell 的好處。就是 Shell 這樣的東西呢,畢竟也算是曆史悠久,酒精考驗的老同志了,所以不容易出現使用者還得自己分辨不同版本下面數學計算究竟應該等於多少這樣的事情。。。
@狼大人 和 @yegle 說的都很有道理,不過我覺得大家都忽視了一點,就是一個軟體的
慣性(或者說是一種習慣)。尤其是 Shell 這種基礎設施的軟體,一旦啟用了一會,很多人很多軟體就會採用這樣的標準,所以只要不是太差一般就不會改變。
舉一個例子吧,我的老師教我使用 Linux 的時候,編輯檔案是用 vi,所以後來有很長一段時間我都不知道 vim 是什麼東西。後來我也一直使用 vi 這個命令,倒不是什麼少一個字母比較方便的問題,就是習慣了。我們也都知道在 Linux 中是沒有 vi 的,至少 debian 是沒有的,預設安裝了 vim-tiny,然後可以安裝完整版的 vim,vi 則一直是 vim 的一個 link。我不知道是我的老師開始的時候用 UNIX 習慣使用 vi,還是我老師的老師是用 UNIX 的然後教他的時候就教了 vi,反正作為從 UNIX 繼承過來的一套軟體,命令的格式、樣式也算是一種慣性,不會也不應該輕易的改變。Linux 中還有很多這樣的例子,比如 cc -> gcc,lex -> flex,yacc -> bison,都是遵循 UNIX 的習慣。
也許是類 UNIX 系統中,有太多太多的指令碼是使用 Shell 指令碼寫的,所以這個不應該輕易的改變。比如,如果我們自己編譯過一些軟體或者類庫,我們一定會對 ./configure 這個檔案不會陌生,這個就是一個用 Shell 寫(準確的應該說是產生的)的指令碼。開啟這個檔案的第一行,你會看到
#! /bin/sh 這樣的一段。我們都知道 sh 和 bash 是不一樣的,sh 作為一種古老的 Shell,在 Linux 中已經基本上被 繼任者 bash 代替了,但是那些 autoconf 的指令碼依然繼承了 sh 這個古老的慣性,也是為了相容其他的系統吧,比如在 FreeBSD 中,預設安裝就是沒有 bash 的。
所以,倒也不是哪一個好或者是哪一個不好,就是大家都習慣了,反正也沒有什麼太大的問題,幾十年了也不好再改了。原因很簡單,曆史習慣+沒人做。
說python不能做shell的我就呵呵了,知道scsh嗎?scheme都能做shell憑啥python不能?說起來丟人,當初我還真動手要做一個pysh,弄了兩周弄到相容不同終端類型的時候實在不勝其煩放棄了。當時互動、解釋執行、基本的iO、管道都已經有雛形了。我覺得是完全可以取代的。給你們看一下 clojure 如何調用 shell:
(require '[me.raynes.conch :refer [programs with-programs let-programs] :as sh])user> (programs echo)#'user/echouser> (echo "Hi!")"Hi!\n"user> (programs cat)#'user/catuser> (cat {:in "hi"})"hi"user> (cat {:in ["hi" "there"]})"hi\nthere\n"
對於複雜的邏輯,python具有模組化的特性,比shell更好用。
但是對於單條命令,用python是什麼感受,每一條命令都要調用 http://os.xxx
,而且python的函數不像shell那樣空格分隔,而是要加括弧、逗號和引號的,那畫面太美我不敢想。
所以最好的方案就是兩者並存,直接敲命令用shell,寫指令碼用python。事實上很多linux發行版內建python,用python取代shell寫指令碼是沒問題的。@餘天升 同學說的“慣性”這一點很有道理,但身邊有不少人,用 bash 多年之後在別人的推薦下改用了 zsh (包括我),幾天就完全切換完成了。在得知 Debian 系中 vi 只是 vim 的別名之後,養成打 vim 而不是 vi 的習慣的,也大有人在。因此,我認為特殊的不是 bash,而是 shell 這一類東西。shell 和其他指令碼語言的區別是很重要的。
所謂“shell”,首先得是
作業系統介面(這也是 shell 的原義),其次才是一個程式設計語言。而作業系統的職能中,檔案系統和進程管理是兩塊很重要的地方。因此 shell 十分強調
檔案和
命令,這是其他指令碼語言所不具備的。具體強調的方式,有語義上的,也有文法上的。
考慮最簡單的,用 vim 開啟檔案 a.c,用 shell 寫是:
vim a.c
很顯然,bash更簡潔Python/Ruby/Perl 沒有取代 Bash 的必要,Bash 是一個 Domain-Specific Language,而 Python 是個 General-purpose Programming Language,語言本身存在的目的本就不同,這也正是 DSL 存在的意義,可以參看維基百科相關條目。
我們討論這個問題的前提是在 *nix 的背景下,那就應該從 *nix 自身的發展曆史尋找原因,也就不難理解為什麼 Python 永遠不會做為 Shell 的替代存在。
Unix 的初期硬體條件的限制決定了 *nix 的設計哲學,其中最重要的兩點就是:一、一個工具只做一件事,並把它做好;二、工具之間通過 plain text 進行資料交換。這樣的設計降低了系統的複雜度,只需要 Shell 這樣的
膠水語言通過搭積木的方式即可完成很多複雜的任務。由於並不需要複雜的資料結構操作,Shell 不需要成為像 Python 或者 Perl 這樣完整的程式語言,而且這一條件到現在也沒有發生變化。
這裡我比較贊同 @yegel 的觀點,至於 @狼大人 對於 Bash 文法的吐槽,我相信在未來相當長一段時間 Bash 的文法不會徹底的改變。因為在 *nix 的世界裡,Shell 的實現並不只有 Bash,可移植性是一個很重要的因素,被 @狼大人 吐槽的那些奇葩文法大部分都是 POSIX 定義的,也正是要感謝 POSIX 的存在,我們才能享受 *nix 帶來的各種好處。
另外,具有互動模式的語言並不一定就能做為 Shell,成為 Shell 的一個必要條件是符合 *nix 的設計哲學,成為一個膠水語言,做為工具之間溝通的媒介,至少實現
pipe 是必不可少的。因為:
BASH 是拿來
“用”的
python 是拿來“
編“的python?你想每次都call(["ls", "path"])一次嗎?打括弧一點都不好玩=。=