Windows命令行和Linux差在哪裡?
看到大家都很嫌棄Windows自帶的命令行工具(命令提示符和PowerShell),那麼它們到底和Linux的命令行差在哪裡?
差在哪?差在軟體生態啊。
拿操作系統為例的話,你用的不是操作系統,你用的是操作系統之上的各種app。一個操作系統之上有各種優秀的app,那麼哪怕這個操作系統設計得很爛,優化得很差,也是會有很多人用的,至於它優化差的問題可以靠瘋狂堆硬體解決,我說的自然就是____系統。
說回到命令行也是一樣,用戶使用的,其實不是命令行的shell本身,也不是終端模擬器程序,而是,大量的基於命令行的app,以及這些app之間的搭配。
大量的基於命令行的那些Linux app形成了肌肉記憶,旁人只道我在命令行運指如飛,可不知道要達到這種狀態是經過了多長時間的歷史積澱。而Linux命令行的應用生態,豐富得讓你可以實現操作系統中需要做到的幾乎所有事情。
Windows下,沒有這成百上千的基於命令行的app,沒有這些讓人已經習慣成自然的app,沒法使用就像吃飯喝水一般自然的這些命令行app,自然,Windows命令行就沒辦法好用:因為基於Windows命令行的軟體生態太貧瘠了。
這,其實與PowerShell還是bash並沒有什麼直接關係。
--
補充:有的人認為ps在設計理念上全方位超越bash。這句話粗看起來似乎有道理,然而,一個shell它首先是一個命令行,其次才是個批處理編程語言。
使用更先進編程理念的shell從來就沒能在普及層面戰勝目前的shell,因為他們忽略了,手工輸入的方便快捷才是shell的第一需求。
Windows 在很長一段時間內,自帶的終端模擬器都一言難盡:難以配置,默認情況下很醜陋,複製粘貼的邏輯很彆扭等等,直到 Windows Terminal 出來才緩解了這個狀況,但 Windows Terminal 到目前還不是默認的終端模擬器,單純這個原因就讓 Windows 的終端體驗下降很多。
另一個問題是補全問題。雖然現在 PowerShell 支持的補全功能並不弱,但糟糕的是,沒有幾個第三方工具適配了 ps 補全功能,對於沒有適配的工具,補全工具基本只能用來補全路徑,而 bash 上補全適配狀態要好的多。而且,Linux 上命令補全通常是漸進式的,每次按下 TAB 都會補全到最長的公共前綴上,並展示可能的命令,而到了 Windows 上 TAB 補全就變成了在輸入處遍歷可能的補全列表,按過頭了還需要再循環一圈,想回退到按 TAB 前的狀態還只能手動退格……也許是我習慣問題,但我覺得 Linux 上默認的的補全邏輯遠遠比 Windows 上更加易用。
至於 Shell 方面,cmd 更是一言難盡,我也不多說了。PowerShell 設計上很不錯,但我並不認為它適合作為 Shell 來使用,而是更適合用來寫腳本,冗長的命令與選項加上 Windows 的補全邏輯作為 shell 用起來簡直是災難,哪怕 wsl 里運行 pwsh 都比 Windows 上直接運行的 PowerShell 要易用的多的多。另外 PowerShell 啟動速度也要慢於 cmd 慢於 bash,這個問題近期倒是改善了不少,但是用起來還是和 bash 揮之即來招之即去的流暢感有所差距。
再就是 Windows 上命令行生態和 Linux 的差距,這是 Windows 重 GUI 輕 CUI 的風格造成的。Windows 上相當一部分 CUI 應用還是移植自 *nix,由此引來的風格差異也是降低 PowerShell 易用性的重要因素之一。
順帶一提,PowerShell 用來寫腳本不錯,不過我更喜歡 Ammonite 一些:
Ammonite?ammonite.io作為一門語言來說,Ammonite 的功能遠強於 PowerShell,因為它支持的是 Scala 的一個超集。與 PowerShell 能利用 .Net 生態類似,Ammonite 也能夠利用整個 JVM 生態,它甚至支持從遠程 Maven 倉庫自由導入 package,譬如想使用阿里雲的 OSS SDK,只需要這樣:
import $ivy.`com.aliyun.oss:aliyun-sdk-oss:3.9.1`
然後就能導入 SDK 中的類型了:
import com.aliyun.oss.OSSClient
import com.aliyun.oss.model._
更多的功能請參見官網文檔。
這個問題需要從至少 3 個不同的方面來看——首先你得把 Shell 和 Terminal 這兩個概念分開,然後還要考慮的是圍繞命令行界面(CLI)所構建的生態環境。很多人都把他們混在了一起,得出的結論就大不相同甚至截然相反。
Shell 就是真正解釋並執行命令的那個程序,比如 cmd/PowerShell/bash,它們各自使用自己的語言,比如 cmd 使用的語言叫 Batch(批處理)。Terminal 是用來顯示結果、處理輸入輸出的那個程序,Windows 上自帶的叫 conhost,Linux 不同的桌面環境自帶的 Terminal 不同。由於 bash 是大多數 Linux 發行版默認的 shell,下面就都是拿他跟 cmd/PowerShell 作比較了。
從 Shell 語言所提供的功能角度講,Batch 無疑是這三個當中最弱雞的,例如沒有函數(只能用 CALL 和標籤模擬)、沒有 switch-case 等等。PowerShell 功能最強,面向對象、並且與 .net 有良好的互操作性,甚至可以嵌入 C# 代碼:
$id = get-random
$code = @"
using System;
namespace HelloWorld
{
public class Program$id
{
public static void Main(){
Console.WriteLine("Hello world!");
}
}
}
"@
Add-Type -TypeDefinition $code -Language CSharp
iex "[HelloWorld.Program$id]::Main()"
當然 Bash 也能模擬一下面向對象甚至函數式編程,但這不是語言提供的一等功能。PowerShell 也有一個相當明顯的缺點,就是跟 bash 相比太啰唆。
從 Shell 程序所提供的功能角度講,cmd 仍然是最弱雞的,例如歷史記錄無法持久化保存、沒有 profile 支持。PowerShell 目前這兩點都是支持的。
因此如果有人說 cmd(Batch) 比 bash 差,這完全沒有問題。但是要是拿 PowerShell 跟 bash 相比,我認為還是 PS 技高一籌。
下面說一下 Terminal:Windows 自帶的那個 conhost 被 Linux 上一眾 Terminals 吊打我認為毫無問題,隨便就能想得到很多槽點(有一些槽點在 Windows 10 上解決了,但還是很想吐):
- 字體受限
- 顏色受限
- 窗口寬度受限
- 行選擇
- 默認是當前語言的編碼
- 不支持 ANSI terminal code
- 功能上的缺失,比如標籤頁、搜索…
- ……
由於 conhost 在兼容性上無法妥協,因此有了新的 Windows Terminal。還有很多其他的第三方 Terminal,比如 ConEmu,不過這些都不是「系統自帶」的。因此如果有人說 conhost 難用的一批,請不要反駁並加入他們。
最後是圍繞命令行界面所構建的生態。從系統管理與維護的角度講,其實 Windows 與 Linux 並沒有太大差距,比如 Windows ServerCore 就是不帶桌面環境的 Windows Server。還有很多程序專門提供了 PowerShell Module 來對軟體進行管理,例如 CosmosDB Emulator。
但在其他方面(第三方程序的豐富程度、命令行包管理器等),Linux 無疑要比 Windows 強很多,甚至 bash 不喜歡的話還可以換別的。我認為主要原因在於 Linux 的桌面環境不是必需品,用戶用什麼桌面環境、甚至有沒有桌面環境都不一定,而 Windows API 就實實在在在那,還有相當好的兼容性,圖形界面又對普通用戶更友好。這樣的 API 不用白不用,用了不白用,白用誰不用 _(:з」∠)_
拿一個具體例子來說,就是很多人提到的軟體包管理工具 scoop。它的命令行介面就可以凸顯出 Windows 的命令行和 Linux 的命令行有多少差距。
例子一、
scoop install 只能用來安裝新的包,如果這個包已經存在(即使殘缺不全,甚至只有一個空目錄),就提示出錯,只能先用 scoop uninstall 將其卸載然後重新安裝。
比如我安裝 curl,在下載過程中 ctrl + c 退出,再安裝,就會提示這個錯誤: