git 入門教程之 git bash 竟然不支持 tree 命令


開門見山

git bashWindows 用戶安裝 git 時默認安裝的命令行工具,不僅界面漂亮功能也不錯,大多數情況下可以替代 Windows 原生的 cmd 命令行.

然而,git bash 命令行不是萬金油,並不能完全替代 cmd ,詳情請參考 mintty 官網的相關說明.

git-bash-tree-mintty.png

mintty is not a full replacement for the Windows Console window

git bash 命令行默認使用 mintty 作為終端模擬器,而 mintty 官宣表示自己不能完全替代 cmd,也就是說 git bash 可能不具備某些 cmd 命令.

git-bash-setup-terminal.png

舉個簡單的例子,如果想要查看當前目錄的文件結構,最好是以目錄樹的形式展現,聰明的你獲取已經猜到了tree 命令.

git bash 命令行中輸入 tree 命令發現並無此命令.

snowdreams1006@home MINGW64 /g/sublime/test
$ tree
bash: tree: command not found

為了驗證,確實沒有 tree 命令,我們直接打開 git bash 支持的命令文件目錄,查看到底有沒有 tree.exe 文件.

git-bash-bin.gif

git bash 桌面快捷方式右鍵,選擇打開文件位置,當前正處於 git 的安裝目錄,進入.\usr\bin 文件夾.

經過驗證,git bash 支持的命令文件確實沒有發現 tree.exe 文件,因此真的不支持 tree 命令.

然而,cmd 自帶的命令行中輸入 tree 中竟然發現能夠輸出目錄樹,原來 cmd 支持 tree 命令.

G:\sublime\test>tree
卷 工作 的文件夾 PATH 列表
卷序列號為 00000081 CC3C:50D0
G:.
├─cmd
└─git

git-bash-tree-cmd.png

tree 命令其實調用的是 tree.com 並不是常見的 tree.exe 格式.

科普時間

現在我們已經知道 git bash 提供的終端模擬器不支持某些 linux 命令,但是為什么不支持以及如何才能支持這些命令呢?

這些問題必須等我們弄清楚 mintty 的朋友圈關系才能更好地解決上述問題,接下來簡單科普下 mintty 的朋友圈.

關於科普知識的來源,請參考上一篇文章: <<git bash 背后的朋友圈>>

mintty 是什么

MinttyCygwinMSYSMsys2 的終端模擬器,派生項目和 WSL.

mintty 開源終端模擬器,基於 putty 的終端仿真和 Windows 前端頁面.

git-bash-tree-mintty-homepage.png

mintty 作為一款優秀的終端模擬器,不僅是其他系統上默認的終端,也是 git bash 的默認終端.

$ mintty --help
Usage: mintty [OPTION]... [ PROGRAM [ARG]... | - ]

Start a new terminal session running the specified program or the user's shell.
If a dash is given instead of a program, invoke the shell as a login shell.

Options:
  -c, --config FILE     Load specified config file
  -e, --exec            Treat remaining arguments as the command to execute
  -h, --hold never|start|error|always  Keep window open after command finishes
  -i, --icon FILE[,IX]  Load window icon from file, optionally with index
  -l, --log FILE|-      Log output to file or stdout
  -o, --option OPT=VAL  Override config file option with given value
  -p, --position X,Y    Open window at specified coordinates
  -s, --size COLS,ROWS  Set screen size in characters
  -t, --title TITLE     Set window title (default: the invoked command)
  -u, --utmp            Create a utmp entry
  -w, --window normal|min|max|full|hide  Set initial window state
      --class CLASS     Set window class name (default: mintty)
  -H, --help            Display help and exit
  -V, --version         Print version information and exit

如果想要自定義 mintty 終端,在 git bash 命令行界面右鍵選擇選項設置即可打開設置頁面.

git-bash-tree-options.png

mingw 是什么

mingwMinimalist GNU for Windows 的縮寫,是 Microsoft Windows 應用程序的極簡主義開發環境.

git-bash-tree-mingw.png

msys 是什么

MSYSMinimal SYStem 的縮寫,是 Bourne Shell 命令行解釋器系統.作為 Microsoftcmd.exe 的替代品,它提供了一個通用的命令行環境,特別適合與 MinGW 一起使用,用於將許多開源應用程序移植到 MS-Windows平台; 它是 Cygwin-1.3 的輕量級分支,它包含一小部分 Unix 工具,可以幫助實現這一目標.

git-bash-tree-msys.png

cygwin 是什么

大量 GNU 和開源工具,提供類似於 Windows 上的 Linux 發行版的功能.

git-bash-tree-cygwin.png

gnu 是什么

GNUGNU's Not Unix 的遞歸縮寫,是自由軟件操作系統.

git-bash-tree-gnu.png

朋友圈關系梳理

git bash 采用 mintty 作為終端模擬器,而 mintty 終端是 mingw ,msys2cygwin的默認終端,這些"操作系統"或多或少都是 GNU 的一部分.

GNU 是自由軟件運動的成果,提出自由軟件以及自由軟件操作系統概念,源碼開源發布.

正因如此,江山代有才人出,前人栽樹后人乘涼,Cygwin 作為 GNU 一員,提出了要在 Windows 打造出 Linux 的感覺,開發出一套完整的解決方案.

或許由於這套方案太完整,功能齊全因而軟件包體積龐大,因此 MinGWMSYS 分別在其基於上進行精簡重構,保留最簡功能,發展出"極簡主義的GNU".

開源的力量是可持續的,慢慢的,這些操作系統的內置終端功能也被單獨提取出來,mintty 作為他們的默認終端也逐漸獨立提供終端模擬器服務,輕松和各個系統進行安裝集成.

說到開源,自然是少不了 git 的身影,分布式版本控制系統這種優秀工具應該造福全人類,然而 git 本身僅支持類 Unix 系統,並不提供 WIndows 系統的支持.

Git For Windows 組織出手增加了 gitWindows 系統的支持,背后的技術多半離不開上述介紹的 GNU 操作系統.

Git Bash Here 則是 Git For Windows 的命令行工具,使用的終端模擬器就是明星模擬器 mintty.

git-bash-mintty-summary.png

回到正題

弄清楚事情的來龍去脈后,對我們解決問題有什么幫助呢?

幫助可大了去了,刨根問題找到了源頭,問題自然迎刃而解!

我勸少年放棄吧

你確定不是在逗我?讓我直接放棄?

git-bash-tree-abandon.jpg

親,真的抱歉呢,放棄是解決問題的最快途徑!

...

談一談為什么要放棄?

git bash 命令行使用的是 mintty 終端,而 mintty 終端並不能完全替代 cmd ,也沒有提供包管理工具供我們擴展第三方命令.

所以默認情況下,如果沒有提供某些命令,那我們只好放棄在 git bash 命令行中使用這些命令.

此路不通,自然會尋求其他解決途徑,比如可以借助 cmd 命令行或者其他第三方軟件等,沒必要非要堅持使用git bash!

既然本文是 tree 命令引發的討論,那就談點和主題有關的技能點,不然豈不是跑題了?

tree 命令雖然 git bash 不提供,但是 cmd 卻已經內置了.

值得注意的是,cmd 提供的 tree 命令比較特殊,並不是常見的 .exe 結尾文件,而是 .com 結尾的文件.

所以 git bash 中輸入 tree 命令時,自身 /usr/bin 中沒有 tree.exe 文件,而系統中也沒有 tree.exe 命令,那么就會提示找不到命令了啊!

手動補全命令

那么第一種調用方法便是補全后綴名,這樣自然能夠調用 cmdtree.com 命令.

git-bash-tree-cmd.com.png

git bash 並不識別 .com 后綴的命令,輸入 tree 命令時以為是 tree.exe ,實際上 tree 命令應該是 tree.com 的簡寫.

我擦,竟然出現亂碼,根據我多年的開發經驗來看,亂碼問題多半是編碼問題導致的,那么修改下終端的編碼設置應該就能解決問題.

git-bash-tree-encoding-utf8.png

在命令行窗口內右鍵彈出 mintty 終端的設置頁面,選擇文本(Text)中本地化(Locale)配置,選擇中文簡體(zh_CN),字符集(Character set)設置為UTF-8.

git-bash-tree-encoding-fail.png

瞬間被打臉,無論是原來的git bash 命令行窗口還是新開的命令行窗口,仍然還是亂碼!

然而,我是不會承認被打臉的,世人皆醉我獨醒,肯定是 bug,哈哈!

其實,中文亂碼真的是 bug ,還是官方認可的 bug 喲,我並沒有被打臉呢,后續會介紹.

調用 cmd 程序

既然git bash 沒有提供 tree 命令,而恰巧 cmd 提供了 tree 命令,那為何不假借他人之手實現自己的目的呢?

cmd 中使用 tree 命令直接輸入即可得到目錄樹結構,但是現在需要在 git bash 中調用 cmd 中的 tree 命令.

# 直接輸入 `tree` 命令,正確響應並且無中文亂碼.
G:\sublime\test>tree
卷 工作 的文件夾 PATH 列表
卷序列號為 00000093 CC3C:50D0
G:.
├─cmd
└─git

# 輸入 `cmd tree` 命令,雖無報錯,但也沒有正確響應.
G:\sublime\test>cmd tree
Microsoft Windows [版本 6.3.9600]
(c) 2013 Microsoft Corporation。保留所有權利。

cmd 中直接輸入 tree 命令即可,無需通過 cmd tree 這種方式,還以為你要調用 cmd 命令呢!

因此,我們需要告訴git bash 要通過 cmd 去調用下 tree 命令.

# 注意看前綴是 `snowdreams1006@home MINGW64` 表明當前處於 `git bash` 環境
snowdreams1006@home MINGW64 /g/sublime/test
# 輸入 `cmd tree` 命令,雖無報錯,但也沒有正確響應,並且仍然有中文亂碼.
$ cmd tree
Microsoft Windows [▒汾 6.3.9600]
(c) 2013 Microsoft Corporation▒▒▒▒▒▒▒▒▒▒Ȩ▒▒▒▒
# 輸出 `tree` 命令,正確響應但有中文亂碼.此時命令行前綴已經更改為 `G:\sublime\test>` 表明當前不再處於`git bash` 環境!
G:\sublime\test>tree
tree
▒▒ ▒▒▒▒ ▒▒▒ļ▒▒▒ PATH ▒б▒
▒▒▒▒▒к▒Ϊ 0000006B CC3C:50D0
G:.
▒▒▒▒cmd
▒▒▒▒git

通過上述操作結果來看,不難發現以下問題.

  • cmd tree 命令切換到 cmd 環境,並且tree 命令並沒有執行.
    換句話說,cmd treecmd dir 或者 cmd 的作用相同,都是切換了當前 bash 環境.
  • 進入 cmd 命令行運行 tree 能夠得到正確響應,但存在中文亂碼.
  • 想要退出 cmd 環境,Ctrl + C 組合即可重新回到 git bash 環境.

由此可見,不加任何參數冒昧進入到 cmd 環境還是比較麻煩的,因此下面提供帶參數的命令幫助我們閱后即焚.

cmd //c tree 命令,閱后即焚,表示執行完立即退出.

snowdreams1006@home MINGW64 /g/sublime/test
$ cmd //c tree
▒▒ ▒▒▒▒ ▒▒▒ļ▒▒▒ PATH ▒б▒
▒▒▒▒▒к▒Ϊ 00000008 CC3C:50D0
G:.
▒▒▒▒cmd
▒▒▒▒git
snowdreams1006@home MINGW64 /g/sublime/test
$

執行命令前后我們都在 git bash 環境並且在 cmd 中得到正確響應結果,唯一的區別就是多加了 //c 參數,表示執行完命令立即退出 cmd 環境.

優雅調用 cmd

簡單總結下,如何在 git bash 中借助 cmd 實現 tree 命令.

  • tree.com : 補全調用命令后綴名,直接調用系統命令.
  • cmd //c tree : 借助 cmd 運行 tree 命令,從而實現調用 tree 的目的.
  • 這兩種方式都存在中文亂碼問題,即使設置了終端的編碼方式也沒有解決亂碼.

調用 tree 命令的目的已經達到,沒有解決的問題是中文亂碼.

解決問題最快速的方式是百度一下或者從官網尋求幫助,這次我選擇后者,因為百度一下人人都會,不用我再講了吧!

git-bash-tree-mintty-winpty.png

簡單解釋下這段話的意思:

如果在 mintty 終端調用原生 cmd 程序,簡單的輸出指令沒有什么問題,交互指令可能存在問題.
因此建議使用 winpty 進行包裝再調用原生 cmd 程序.

winpty 是一種提供與cmd 通信的軟件包,詳情請參考https://github.com/rprichard/winpty

git-bash-tree-winpty-github.png

有什么神奇之處?不妨加上 winpty 試試看!

snowdreams1006@home MINGW64 /g/sublime/test
# `winpty` + `tree.com` : 正常輸出且無中文亂碼 
$ winpty tree.com
卷 工作 的文件夾 PATH 列表
卷序列號為 00000074 CC3C:50D0
G:.
├─cmd
└─git

snowdreams1006@home MINGW64 /g/sublime/test
# `winpty` + `cmd //c tree` : 正常輸出且無中文亂碼
$ winpty cmd //c tree
卷 工作 的文件夾 PATH 列表
卷序列號為 000000B3 CC3C:50D0
G:.
├─cmd
└─git

snowdreams1006@home MINGW64 /g/sublime/test
$

果然是神葯,一下子就治好了我多年的老寒腿啊!

  • winpty tree.com : 不叫小名而叫全稱,直接調用系統命令
  • winpty cmd //c tree : 假借他人之手,變相調用系統命令

上文中說設置文件編碼應該能夠解決中文亂碼問題結果仍然有亂碼,猜測是 bug ,現在沒有打臉吧?

既然已經提供了解決方案,那文章是不是應該到此為止了呢?

不不不,遠遠還沒結束,這只是開胃小菜,好戲還在后頭呢.

更何況這命令也忒長了,記不住啊!

很簡單,可以設置別名啊,把常用命令設置成別名,這樣就記住啦!

輸入 alias 命令沒有報錯,說明目前環境是支持設置別名的.

snowdreams1006@home MINGW64 /g/sublime/test
$ alias
alias ll='ls -l'
alias ls='ls -F --color=auto --show-control-chars'
alias node='winpty node.exe'

按照 linux 的操作習慣,命令行設置的一般都是臨時性的,想要永久生效,都要寫入到文件中,別名這種當然要一勞永逸設置成永久文件.

snowdreams1006@home MINGW64 /g/sublime/test
$ cat /etc/bashrc
cat: /etc/bashrc: No such file or directory

snowdreams1006@home MINGW64 /g/sublime/test
$ cat ~/.bashrc
cat: /c/Users/snowdreams1006/.bashrc: No such file or directory

竟然配置文件都不存在?

git-bash-tree-winpty-github.png

當然不存在了啊!快醒醒,你是在 Windows 系統上並不是 Linux 系統,上哪給你弄這些配置文件去?

腦海中迅速閃現哲學基本問題: 我是誰,我在那,我在干什么?

我是 Windows 系統用戶,正在 git bash 命令行中試圖設置別名,沒有找到類似於 linux 配置文件.

既然你明白你何出來,那你去那里看看有沒有什么發現?

snowdreams1006@home MINGW64 /g/sublime/test
$ cd /e/git
snowdreams1006@home MINGW64 /e/git
$ winpty tree.com
卷 軟件 的文件夾 PATH 列表
卷序列號為 00000063 223E:7300
E:.
├─bin
├─cmd
├─dev
│  ├─mqueue
│  └─shm
├─etc
│  ├─pkcs11
│  ├─pki
│  │  └─ca-trust
│  │      ├─extracted
│  │      │  ├─java
│  │      │  ├─openssl
│  │      │  └─pem
│  │      └─source
│  │          └─anchors
│  ├─profile.d
│  └─ssh
├─mingw64
│  ├─bin
│  ├─doc
│  │  └─git-credential-manager
│  ├─etc
│  │  ├─pkcs11
│  │  └─pki
│  │      └─ca-trust
│  │          └─extracted
│  │              ├─java
│  │              ├─openssl
│  │              └─pem
│  ├─lib
│  │  ├─dde1.4
│  │  ├─engines
│  │  ├─itcl4.0.4
│  │  ├─p11-kit
│  │  ├─pkcs11
│  │  ├─reg1.3
│  │  ├─sqlite3.11.0
│  │  ├─tcl8
│  │  │  ├─8.4
│  │  │  │  └─platform
│  │  │  ├─8.5
│  │  │  └─8.6
│  │  │      └─tdbc
│  │  ├─tcl8.6
│  │  │  ├─encoding
│  │  │  ├─http1.0
│  │  │  ├─msgs
│  │  │  ├─opt0.4
│  │  │  └─tzdata
│  │  │      ├─Africa
│  │  │      ├─America
│  │  │      │  ├─Argentina
│  │  │      │  ├─Indiana
│  │  │      │  ├─Kentucky
│  │  │      │  └─North_Dakota
│  │  │      ├─Antarctica
│  │  │      ├─Arctic
│  │  │      ├─Asia
│  │  │      ├─Atlantic
│  │  │      ├─Australia
│  │  │      ├─Brazil
│  │  │      ├─Canada
│  │  │      ├─Chile
│  │  │      ├─Etc
│  │  │      ├─Europe
│  │  │      ├─Indian
│  │  │      ├─Mexico
│  │  │      ├─Pacific
│  │  │      ├─SystemV
│  │  │      └─US
│  │  ├─thread2.7.3
│  │  └─tk8.6
│  │      ├─demos
│  │      │  └─images
│  │      ├─images
│  │      ├─msgs
│  │      └─ttk
│  ├─libexec
│  │  └─git-core
│  │      └─mergetools
│  ├─share
│  │  ├─antiword
│  │  ├─doc
│  │  │  ├─connect
│  │  │  ├─git-doc
│  │  │  │  ├─howto
│  │  │  │  └─technical
│  │  │  └─nghttp2
│  │  ├─gettext-0.19.7
│  │  │  └─its
│  │  ├─git
│  │  │  ├─bindimage.txt
│  │  │  └─completion
│  │  ├─git-core
│  │  │  └─templates
│  │  │      ├─hooks
│  │  │      └─info
│  │  ├─git-gui
│  │  │  └─lib
│  │  ├─gitweb
│  │  │  └─static
│  │  ├─licenses
│  │  │  ├─bzip2
│  │  │  ├─expat
│  │  │  ├─gcc-libs
│  │  │  ├─gettext
│  │  │  │  ├─gettext-runtime
│  │  │  │  │  ├─intl
│  │  │  │  │  └─libasprintf
│  │  │  │  ├─gettext-tools
│  │  │  │  │  └─gnulib-lib
│  │  │  │  │      └─libxml
│  │  │  │  └─gnulib-local
│  │  │  │      └─lib
│  │  │  │          └─libxml
│  │  │  ├─libffi
│  │  │  ├─libiconv
│  │  │  │  └─libcharset
│  │  │  ├─libssh2
│  │  │  ├─libsystre
│  │  │  ├─libtasn1
│  │  │  ├─libtre
│  │  │  ├─libwinpthread
│  │  │  │  └─mingw-w64-libraries
│  │  │  │      └─winpthreads
│  │  │  ├─openssl
│  │  │  ├─wineditline
│  │  │  └─zlib
│  │  ├─nghttp2
│  │  ├─p11-kit
│  │  │  └─modules
│  │  ├─perl5
│  │  │  └─site_perl
│  │  │      └─Git
│  │  │          └─SVN
│  │  │              └─Memoize
│  │  └─pki
│  │      └─ca-trust-source
│  └─ssl
│      └─certs
├─tmp
└─usr
    ├─bin
    │  ├─core_perl
    │  └─vendor_perl
    ├─lib
    │  ├─awk
    │  ├─coreutils
    │  ├─gawk
    │  ├─gnupg
    │  │  └─gnupg
    │  ├─openssl
    │  │  └─engines
    │  ├─p11-kit
    │  ├─perl5
    │  │  ├─core_perl
    │  │  │  ├─auto
    │  │  │  │  ├─arybase
    │  │  │  │  ├─attributes
    │  │  │  │  ├─B
    │  │  │  │  ├─Compress
    │  │  │  │  │  └─Raw
    │  │  │  │  │      ├─Bzip2
    │  │  │  │  │      └─Zlib
    │  │  │  │  ├─Cwd
    │  │  │  │  ├─Data
    │  │  │  │  │  └─Dumper
    │  │  │  │  ├─DB_File
    │  │  │  │  ├─Devel
    │  │  │  │  │  ├─Peek
    │  │  │  │  │  └─PPPort
    │  │  │  │  ├─Digest
    │  │  │  │  │  ├─MD5
    │  │  │  │  │  └─SHA
    │  │  │  │  ├─Encode
    │  │  │  │  │  ├─Byte
    │  │  │  │  │  ├─CN
    │  │  │  │  │  ├─EBCDIC
    │  │  │  │  │  ├─JP
    │  │  │  │  │  ├─KR
    │  │  │  │  │  ├─Symbol
    │  │  │  │  │  ├─TW
    │  │  │  │  │  └─Unicode
    │  │  │  │  ├─Fcntl
    │  │  │  │  ├─File
    │  │  │  │  │  ├─DosGlob
    │  │  │  │  │  └─Glob
    │  │  │  │  ├─Filter
    │  │  │  │  │  └─Util
    │  │  │  │  │      └─Call
    │  │  │  │  ├─GDBM_File
    │  │  │  │  ├─Hash
    │  │  │  │  │  └─Util
    │  │  │  │  │      └─FieldHash
    │  │  │  │  ├─I18N
    │  │  │  │  │  └─Langinfo
    │  │  │  │  ├─IO
    │  │  │  │  ├─IPC
    │  │  │  │  │  └─SysV
    │  │  │  │  ├─List
    │  │  │  │  │  └─Util
    │  │  │  │  ├─Math
    │  │  │  │  │  └─BigInt
    │  │  │  │  │      └─FastCalc
    │  │  │  │  ├─MIME
    │  │  │  │  │  └─Base64
    │  │  │  │  ├─mro
    │  │  │  │  ├─NDBM_File
    │  │  │  │  ├─ODBM_File
    │  │  │  │  ├─Opcode
    │  │  │  │  ├─PerlIO
    │  │  │  │  │  ├─encoding
    │  │  │  │  │  ├─mmap
    │  │  │  │  │  ├─scalar
    │  │  │  │  │  └─via
    │  │  │  │  ├─POSIX
    │  │  │  │  ├─re
    │  │  │  │  ├─SDBM_File
    │  │  │  │  ├─Socket
    │  │  │  │  ├─Storable
    │  │  │  │  ├─Sys
    │  │  │  │  │  ├─Hostname
    │  │  │  │  │  └─Syslog
    │  │  │  │  ├─threads
    │  │  │  │  │  └─shared
    │  │  │  │  ├─Tie
    │  │  │  │  │  └─Hash
    │  │  │  │  │      └─NamedCapture
    │  │  │  │  ├─Time
    │  │  │  │  │  ├─HiRes
    │  │  │  │  │  └─Piece
    │  │  │  │  ├─Unicode
    │  │  │  │  │  └─Collate
    │  │  │  │  ├─Win32
    │  │  │  │  ├─Win32API
    │  │  │  │  │  └─File
    │  │  │  │  └─Win32CORE
    │  │  │  ├─B
    │  │  │  ├─Compress
    │  │  │  │  └─Raw
    │  │  │  ├─CORE
    │  │  │  ├─Data
    │  │  │  ├─Devel
    │  │  │  ├─Digest
    │  │  │  ├─Encode
    │  │  │  │  ├─CN
    │  │  │  │  ├─JP
    │  │  │  │  ├─KR
    │  │  │  │  ├─MIME
    │  │  │  │  │  └─Header
    │  │  │  │  └─Unicode
    │  │  │  ├─File
    │  │  │  │  └─Spec
    │  │  │  ├─Filter
    │  │  │  │  └─Util
    │  │  │  ├─Hash
    │  │  │  │  └─Util
    │  │  │  ├─I18N
    │  │  │  ├─IO
    │  │  │  │  └─Socket
    │  │  │  ├─IPC
    │  │  │  ├─List
    │  │  │  │  └─Util
    │  │  │  ├─Math
    │  │  │  │  └─BigInt
    │  │  │  ├─MIME
    │  │  │  ├─PerlIO
    │  │  │  ├─Scalar
    │  │  │  ├─Sub
    │  │  │  ├─Sys
    │  │  │  ├─threads
    │  │  │  ├─Tie
    │  │  │  │  └─Hash
    │  │  │  ├─Time
    │  │  │  ├─Unicode
    │  │  │  │  └─Collate
    │  │  │  └─Win32API
    │  │  └─vendor_perl
    │  │      ├─auto
    │  │      │  ├─HTML
    │  │      │  │  └─Parser
    │  │      │  ├─Net
    │  │      │  │  └─SSLeay
    │  │      │  ├─SVN
    │  │      │  │  ├─_Client
    │  │      │  │  ├─_Core
    │  │      │  │  ├─_Delta
    │  │      │  │  ├─_Fs
    │  │      │  │  ├─_Ra
    │  │      │  │  ├─_Repos
    │  │      │  │  └─_Wc
    │  │      │  └─Term
    │  │      │      └─ReadKey
    │  │      ├─HTML
    │  │      ├─Net
    │  │      │  └─SSLeay
    │  │      ├─SVN
    │  │      └─Term
    │  ├─pkcs11
    │  ├─sasl2
    │  ├─ssh
    │  ├─tar
    │  └─terminfo
    │      ├─63
    │      ├─64
    │      └─78
    ├─libexec
    ├─share
    │  ├─bash-completion
    │  │  └─completions
    │  ├─cygwin
    │  ├─git
    │  ├─gnupg
    │  ├─licenses
    │  │  ├─curl
    │  │  ├─dos2unix
    │  │  ├─expat
    │  │  ├─file
    │  │  ├─gcc-libs
    │  │  ├─libffi
    │  │  ├─libsasl
    │  │  ├─libsqlite
    │  │  ├─libssh2
    │  │  ├─mintty
    │  │  ├─ncurses
    │  │  ├─openssh
    │  │  ├─openssl
    │  │  ├─p11-kit
    │  │  ├─perl-Net-SSLeay
    │  │  ├─perl-TermReadKey
    │  │  ├─unzip
    │  │  ├─vim
    │  │  └─zlib
    │  ├─misc
    │  ├─p11-kit
    │  │  └─modules
    │  ├─perl5
    │  │  ├─core_perl
    │  │  │  ├─App
    │  │  │  │  └─Prove
    │  │  │  │      └─State
    │  │  │  │          └─Result
    │  │  │  ├─Archive
    │  │  │  │  └─Tar
    │  │  │  ├─Attribute
    │  │  │  ├─autodie
    │  │  │  │  ├─exception
    │  │  │  │  └─Scope
    │  │  │  ├─B
    │  │  │  ├─Carp
    │  │  │  ├─Class
    │  │  │  ├─Compress
    │  │  │  ├─Config
    │  │  │  │  └─Perl
    │  │  │  ├─CPAN
    │  │  │  │  ├─Exception
    │  │  │  │  ├─FTP
    │  │  │  │  ├─HTTP
    │  │  │  │  ├─Kwalify
    │  │  │  │  ├─LWP
    │  │  │  │  ├─Meta
    │  │  │  │  └─Plugin
    │  │  │  ├─DBM_Filter
    │  │  │  ├─Devel
    │  │  │  ├─Digest
    │  │  │  ├─Encode
    │  │  │  ├─encoding
    │  │  │  ├─Exporter
    │  │  │  ├─ExtUtils
    │  │  │  │  ├─CBuilder
    │  │  │  │  │  └─Platform
    │  │  │  │  │      └─Windows
    │  │  │  │  ├─Command
    │  │  │  │  ├─Constant
    │  │  │  │  ├─Liblist
    │  │  │  │  ├─MakeMaker
    │  │  │  │  │  └─version
    │  │  │  │  ├─ParseXS
    │  │  │  │  └─Typemaps
    │  │  │  ├─File
    │  │  │  ├─Filter
    │  │  │  ├─Getopt
    │  │  │  ├─HTTP
    │  │  │  ├─I18N
    │  │  │  │  └─LangTags
    │  │  │  ├─IO
    │  │  │  │  ├─Compress
    │  │  │  │  │  ├─Adapter
    │  │  │  │  │  ├─Base
    │  │  │  │  │  ├─Gzip
    │  │  │  │  │  ├─Zip
    │  │  │  │  │  └─Zlib
    │  │  │  │  ├─Socket
    │  │  │  │  └─Uncompress
    │  │  │  │      └─Adapter
    │  │  │  ├─IPC
    │  │  │  ├─JSON
    │  │  │  │  └─PP
    │  │  │  ├─Locale
    │  │  │  │  ├─Codes
    │  │  │  │  └─Maketext
    │  │  │  ├─Math
    │  │  │  │  ├─BigFloat
    │  │  │  │  └─BigInt
    │  │  │  ├─Memoize
    │  │  │  ├─Module
    │  │  │  │  ├─CoreList
    │  │  │  │  └─Load
    │  │  │  ├─Net
    │  │  │  │  └─FTP
    │  │  │  ├─overload
    │  │  │  ├─Params
    │  │  │  ├─Parse
    │  │  │  │  └─CPAN
    │  │  │  ├─Perl
    │  │  │  ├─PerlIO
    │  │  │  │  └─via
    │  │  │  ├─Pod
    │  │  │  │  ├─Perldoc
    │  │  │  │  ├─Simple
    │  │  │  │  └─Text
    │  │  │  ├─Search
    │  │  │  ├─TAP
    │  │  │  │  ├─Formatter
    │  │  │  │  │  ├─Console
    │  │  │  │  │  └─File
    │  │  │  │  ├─Harness
    │  │  │  │  └─Parser
    │  │  │  │      ├─Iterator
    │  │  │  │      ├─Result
    │  │  │  │      ├─Scheduler
    │  │  │  │      ├─SourceHandler
    │  │  │  │      └─YAMLish
    │  │  │  ├─Term
    │  │  │  ├─Test
    │  │  │  │  ├─Builder
    │  │  │  │  │  ├─IO
    │  │  │  │  │  └─Tester
    │  │  │  │  ├─Tester
    │  │  │  │  └─use
    │  │  │  ├─Text
    │  │  │  ├─Thread
    │  │  │  ├─Tie
    │  │  │  ├─Time
    │  │  │  ├─Unicode
    │  │  │  │  └─Collate
    │  │  │  │      └─CJK
    │  │  │  ├─unicore
    │  │  │  │  ├─lib
    │  │  │  │  │  ├─Age
    │  │  │  │  │  ├─Alpha
    │  │  │  │  │  ├─Bc
    │  │  │  │  │  ├─BidiC
    │  │  │  │  │  ├─BidiM
    │  │  │  │  │  ├─Blk
    │  │  │  │  │  ├─Bpt
    │  │  │  │  │  ├─Cased
    │  │  │  │  │  ├─Ccc
    │  │  │  │  │  ├─CE
    │  │  │  │  │  ├─CI
    │  │  │  │  │  ├─CompEx
    │  │  │  │  │  ├─CWCF
    │  │  │  │  │  ├─CWCM
    │  │  │  │  │  ├─CWKCF
    │  │  │  │  │  ├─CWL
    │  │  │  │  │  ├─CWT
    │  │  │  │  │  ├─CWU
    │  │  │  │  │  ├─Dash
    │  │  │  │  │  ├─Dep
    │  │  │  │  │  ├─DI
    │  │  │  │  │  ├─Dia
    │  │  │  │  │  ├─Dt
    │  │  │  │  │  ├─Ea
    │  │  │  │  │  ├─Ext
    │  │  │  │  │  ├─Gc
    │  │  │  │  │  ├─GCB
    │  │  │  │  │  ├─GrBase
    │  │  │  │  │  ├─Hex
    │  │  │  │  │  ├─Hst
    │  │  │  │  │  ├─Hyphen
    │  │  │  │  │  ├─IDC
    │  │  │  │  │  ├─Ideo
    │  │  │  │  │  ├─IDS
    │  │  │  │  │  ├─In
    │  │  │  │  │  ├─Jg
    │  │  │  │  │  ├─Jt
    │  │  │  │  │  ├─Lb
    │  │  │  │  │  ├─LOE
    │  │  │  │  │  ├─Lower
    │  │  │  │  │  ├─Math
    │  │  │  │  │  ├─NChar
    │  │  │  │  │  ├─NFCQC
    │  │  │  │  │  ├─NFDQC
    │  │  │  │  │  ├─NFKCQC
    │  │  │  │  │  ├─NFKDQC
    │  │  │  │  │  ├─Nt
    │  │  │  │  │  ├─Nv
    │  │  │  │  │  ├─PatSyn
    │  │  │  │  │  ├─PatWS
    │  │  │  │  │  ├─Perl
    │  │  │  │  │  ├─QMark
    │  │  │  │  │  ├─SB
    │  │  │  │  │  ├─Sc
    │  │  │  │  │  ├─Scx
    │  │  │  │  │  ├─SD
    │  │  │  │  │  ├─STerm
    │  │  │  │  │  ├─Term
    │  │  │  │  │  ├─UIdeo
    │  │  │  │  │  ├─Upper
    │  │  │  │  │  ├─WB
    │  │  │  │  │  ├─XIDC
    │  │  │  │  │  └─XIDS
    │  │  │  │  └─To
    │  │  │  ├─User
    │  │  │  ├─version
    │  │  │  ├─warnings
    │  │  │  └─Win32API
    │  │  │      └─File
    │  │  └─vendor_perl
    │  │      ├─Authen
    │  │      │  └─SASL
    │  │      │      └─Perl
    │  │      ├─Convert
    │  │      ├─Date
    │  │      │  └─Language
    │  │      ├─Encode
    │  │      ├─Error
    │  │      ├─File
    │  │      ├─HTML
    │  │      ├─HTTP
    │  │      │  ├─Cookies
    │  │      │  ├─Headers
    │  │      │  └─Request
    │  │      ├─IO
    │  │      │  └─Socket
    │  │      │      └─SSL
    │  │      ├─LWP
    │  │      │  ├─Authen
    │  │      │  └─Protocol
    │  │      ├─Mail
    │  │      │  ├─Field
    │  │      │  └─Mailer
    │  │      ├─MIME
    │  │      │  ├─Decoder
    │  │      │  ├─Field
    │  │      │  └─Parser
    │  │      ├─Net
    │  │      │  ├─HTTP
    │  │      │  └─SMTP
    │  │      ├─Time
    │  │      ├─URI
    │  │      │  ├─file
    │  │      │  └─urn
    │  │      └─WWW
    │  │          └─RobotRules
    │  ├─pki
    │  │  └─ca-trust-source
    │  ├─tabset
    │  ├─terminfo
    │  │  ├─63
    │  │  ├─64
    │  │  └─78
    │  └─vim
    │      └─vim74
    │          ├─autoload
    │          │  └─xml
    │          ├─colors
    │          ├─compiler
    │          ├─doc
    │          ├─ftplugin
    │          ├─indent
    │          ├─keymap
    │          ├─macros
    │          │  ├─hanoi
    │          │  ├─life
    │          │  ├─maze
    │          │  └─urm
    │          ├─pack
    │          │  └─dist
    │          │      └─opt
    │          │          ├─dvorak
    │          │          │  ├─dvorak
    │          │          │  └─plugin
    │          │          ├─editexisting
    │          │          │  └─plugin
    │          │          ├─justify
    │          │          │  └─plugin
    │          │          ├─matchit
    │          │          │  ├─doc
    │          │          │  └─plugin
    │          │          ├─shellmenu
    │          │          │  └─plugin
    │          │          └─swapmouse
    │          │              └─plugin
    │          ├─plugin
    │          ├─print
    │          ├─spell
    │          ├─syntax
    │          ├─tools
    │          └─tutor
    └─ssl
        ├─certs
        └─misc

看到熟悉的 ./etc/bash.bashrc 文件,頓時親切不少,設置一下別名再說.

snowdreams1006@home MINGW64 /e/git
$ echo "# Set alias for tree command" >> ./etc/bash.bashrc
snowdreams1006@home MINGW64 /e/git
$ echo "alias tree='winpty tree.com'" >> ./etc/bash.bashrc
snowdreams1006@home MINGW64 /e/git
$ source ./etc/bash.bashrc

現在測試一下能否正確打印出目錄樹:

snowdreams1006@home MINGW64 /e/git
$ cd /g/sublime/test

snowdreams1006@home MINGW64 /g/sublime/test
$ tree
卷 工作 的文件夾 PATH 列表
卷序列號為 000000A3 CC3C:50D0
G:.
├─cmd
└─git

親測有效,通過設置別名的方式可以簡化命令,從而實現在 git bash 中優雅調用 tree 命令.

固執少年一意孤行

少年既然不聽勸,那我只好和你一起一意孤行.

git bash 不支持 tree 命令,意味着 mintty 終端不支持 tree 命令,但 mintty 既然作為一款優秀的終端模擬器不可能不支持 tree 命令,否則 cygwin ,msys2mingw 等系統不可能將其作為默認終端.

回想起 linux 系統,最小化安裝版也不支持 tree 命令,通過包管理工具自行擴展即可支持 tree 命令.

因此,思路有兩種,像 linux 那樣通過包管理工具安裝 tree 命令,或者通過源碼編譯方式擴展 tree 命令.

第一種需要包管理工具,而git bash 使用的是 mintty 終端,並沒有提供相應的包管理工具.
所以想要通過包管理工具進行安裝 tree 命令也是無路可走.

包管理工具安裝

如果能夠提供包管理工具,那么我們就可以像 linux 系統那樣安裝第三方命令一樣,安裝 tree 命令了.

首先想到的是 mintty 官網有沒有相關說明,遺憾的是,mintty 本身一般是通過包管理工具安裝的,單獨的終端並沒有包管理的環境,因此無法調用相關命令.

git-bash-tree-winpty-github.png

Administrator@snowdreams1006 MINGW64 /f/workspace/test
$ mingw-get
bash: mingw-get: command not found

Administrator@snowdreams1006 MINGW64 /f/workspace/test
$ pacman
bash: pacman: command not found

然而,小小的挫折是不會輕易放棄的,既然 mintty 官網不能提供有效的幫助,那我們回到最初安裝 git 的地方,看一下 git 能否提供相關的包管理工具.

git-bash-tree-download-gitforwindows.png

頻繁出現 Git For Windows 名詞,根據軟件的命令規則,Git for Windows 可能是獨立的軟件,更何況 git bash 集成的終端也不是自身研發的終端而是第三方的 mintty 終端.

所以,我們有理由相信 Git for Windows 是另外的團隊在維護,而不是 Git 團隊.

git-bash-tree-download-gitforwindows.png

git-for-windows 官網: https://gitforwindows.org/

git-bash-tree-gitforwindows-build-extra.png

根據官方說明,安裝后正在下載相關依賴,下載速度比較慢的話,請自行解決.

git-bash-tree-gitforwindows-build-extra.png

下載完成后,原來的 cmd 窗口會自動關閉並且打開新的 git bash 窗口.

git-bash-gitbash-install.png

Administrator@snowdreams1006 MINGW64 / (master)
$ sdk help
The 'sdk' shell function helps you to get up and running
with the Git for Windows SDK. The available subcommands are:

create-desktop-icon: install a desktop icon that starts the Git for
    Windows SDK Bash.

cd <project>: initialize/update a worktree and cd into it. Known projects:
        git git-extra msys2-runtime installer build-extra
        MINGW-packages MSYS2-packages mingw-w64-busybox mingw-w64-curl
        mingw-w64-cv2pdb mingw-w64-git mingw-w64-git-credential-manager
        mingw-w64-git-lfs mingw-w64-git-sizer mingw-w64-wintoast bash
        curl gawk git-flow gnupg heimdal mintty nodejs openssh openssl
        perl perl-HTML-Parser perl-Locale-Gettext perl-Net-SSLeay
        perl-TermReadKey perl-XML-Parser perl-YAML-Syck subversion tig

init <project>: initialize and/or update a worktree. Known projects
    are the same as for the 'cd' command.

build <project>: builds one of the following:
        git-and-installer git git-extra msys2-runtime installer
        mingw-w64-busybox mingw-w64-curl mingw-w64-cv2pdb mingw-w64-git
        mingw-w64-git-credential-manager mingw-w64-git-lfs
        mingw-w64-git-sizer mingw-w64-wintoast bash curl gawk
        git-flow gnupg heimdal mintty nodejs openssh openssl
        perl perl-HTML-Parser perl-Locale-Gettext perl-Net-SSLeay
        perl-TermReadKey perl-XML-Parser perl-YAML-Syck subversion tig

edit <file>: edit a well-known file. Well-known files are:
        git-sdk.sh sdk.completion ReleaseNotes.md install.iss

reload: reload the 'sdk' function.

現在安裝完成后,我們再次打開 Git for Windows 的開發文檔簡介,從中不難發現該項目使用了 MSYS2 項目,那么問題迎刃而解.

git-bash-tree-gitforwindows-msys2.png

根據科普知識,我們知道 MSYS2MinGW 都是操作系統,而 Git For Windows 將兩者結合在一起,默認使用 MSYS2 的包管理工具.

Administrator@snowdreams1006 MINGW64 / (master)
$ Pacman -h
用法:  Pacman <操作> [...]
操作:
    Pacman {-h --help}
    Pacman {-V --version}
    Pacman {-D --database} <選項> <軟件包>
    Pacman {-F --files}    [選項] [軟件包]
    Pacman {-Q --query}    [選項] [軟件包]
    Pacman {-R --remove}   [選項] <軟件包>
    Pacman {-S --sync}     [選項] [軟件包]
    Pacman {-T --deptest}  [選項] [軟件包]
    Pacman {-U --upgrade}  [選項] <文件>

使用 'Pacman {-h --help}' 及某個操作以查看可用選項

激動人心的時刻就要來臨,在正式使用 Pacman 安裝 tree 命令外,我們再次檢查當前系統環境以確保沒有 git bash 無法調用 tree 命令.

Administrator@snowdreams1006 MINGW64 / (master)
$ tree
bash: tree: 未找到命令

調用 Pacman -S tree 命令安裝 tree 命令.

Administrator@snowdreams1006 MINGW64 / (master)
$ Pacman -S tree
正在解析依賴關系...
正在查找軟件包沖突...

軟件包 (1) tree-1.8.0-1

下載大小:   0.05 MiB
全部安裝大小:  0.07 MiB

:: 進行安裝嗎? [Y/n] y
警告:沒有 /var/cache/pacman/pkg/ 緩存存在,正在創建...
:: 正在獲取軟件包......
 tree-1.8.0-1-x86_64       51.1 KiB   211K/s 00:00 [#####################] 100%
(1/1) 正在檢查密鑰環里的密鑰                       [#####################] 100%
(1/1) 正在檢查軟件包完整性                         [#####################] 100%
(1/1) 正在加載軟件包文件                           [#####################] 100%
(1/1) 正在檢查文件沖突                             [#####################] 100%
(1/1) 正在檢查可用存儲空間                         [#####################] 100%
:: 正在處理軟件包的變化...
(1/1) 正在安裝 tree      

驗證安裝成功,切換到測試目錄調用 tree 命令真的打印出了目錄樹結構.

Administrator@snowdreams1006 MINGW64 / (master)
$ pwd
/

Administrator@snowdreams1006 MINGW64 / (master)
$ cd /f/workspace/test

Administrator@snowdreams1006 MINGW64 /f/workspace/test
$ tree
.
├── cmd
└── gitbash

2 directories, 0 files

tree.exe 文件確實已經存在,通過這樣方式當然可以安裝任意第三方命令了呢!

Administrator@snowdreams1006 MINGW64 / (master)
$ pwd
/

Administrator@snowdreams1006 MINGW64 / (master)
$ ls usr/bin/tree.exe
usr/bin/tree.exe*

Administrator@snowdreams1006 MINGW64 / (master)
$ ls usr/bin/tree.exe
usr/bin/tree.exe*

然而,事情還沒有結束,雖然打印當前路徑顯示的是在 / ,但是如果從普通的 git bash 命令行窗口進入 /,發現他們並不一致!

git-bash-tree-gitbash-diff.png

開發版左上角文字: SDK-64,普通版左上角: MinGW64.

事情應該不至於這么復雜,我猜測如果進入到 git sdk 的安裝目錄,應該是一樣的!

git-bash-tree-gitbash-in.png

源碼編譯安裝

還有一種源碼編譯安裝方式,可以猜想到的是將會比較麻煩,不僅要安裝 c 編譯環境,還可能會面臨如何移植到 Windows 環境的問題.

恕再下先行一步,告辭!

git-bash-tree-bye.jpg

但是老司機怎么能收走就走,不是說好一起闖天下得嘛?

然而,心有余而力不足,編譯安裝再到測試確實是不少挑戰,最重要的是,電腦太卡了等不了.

所以,收集到了一些資料方便有條件的小伙伴去研究吧!

git-bash-tree-homepage.png

下載鏈接: ftp://mama.indstate.edu/linux/tree/tree-1.8.0.tgz

  • mingw ,msys2 或者 cygwin 系統上編譯安裝 treec 文件,最終生成 tree.exe 可執行文件.
  • 獨立安裝 c 編譯環境,生成的 tree.exe 可執行文件再想辦法兼容到 git bash 所支持的 .exe 類型,或許也不用轉換.
  • 請參考 linux 系統的 tree 命令源碼: http://mama.indstate.edu/users/ice/tree/

我覺得我還可以再堅持一會,雖然不能從頭開始編譯生成 tree.exe 可執行文件,但是研究了這么多朋友圈關系,足夠我找到解決方案了.

tree 命令的源碼文件編譯成 tree.exe 可執行文件比較費勁,但是可以找到已經編譯好的文件啊.

說道這里,不得不提一下神奇的 sourceforge 網站,提供源碼和下載網站.

git-bash-tree-sourceforge-homepage.png

前面我們一直在說 mintty 終端模擬器也好,或者 mingw ,msys2cygwin 操作系統也罷,他們或多或少和 GNU 有一些聯系,而 GNU 是自由軟件操作系統,源碼會隨程序一同發布.

所以我們應該可以從 sourceforge 網站上找到些蛛絲馬跡,說不定還有打包好的可執行文件呢,如果那樣的話就不用我們手動編譯安裝了!

git-bash-tree-sourceforge-search.png

功夫不負有心人,竟然真的找到了,搜索 GNU 發現了 gnuwin32 項目,完整提供了原生命令,其中就有我們需要的 tree 命令.

git-bash-tree-sourceforge-search.png

下載鏈接: https://sourceforge.net/projects/gnuwin32/files/tree/1.5.2.2/tree-1.5.2.2-bin.zip/download

於是下載二進制文件找到其中的 /bin/tree.exe 並將其復制到 /git/usr/bin 目錄下,這樣 git bash 本身就支持 tree 命令了.

首先清除掉上一步設置的別名,防止干擾以確保此二進制文件真實有效.

snowdreams1006@home MINGW64 /g/sublime/test
# 切換到 `git` 安裝目錄
$ cd /e/git

snowdreams1006@home MINGW64 /e/git
# 編輯 `bash.bashrc` 配置文件,移除別名
$ vim ./etc/bash.bashrc

snowdreams1006@home MINGW64 /e/git
# 查看配置文件內容,別名設置已移除
$ tail ./etc/bash.bashrc
[[ "$-" != *i* ]] && return

# Set a default prompt of: user@host, MSYSTEM variable, and current_directory
#PS1='\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[35m\]$MSYSTEM\[\e[0m\] \[\e[33m\]\w\[\e[0m\]\n\$ '

# Uncomment to use the terminal colours set in DIR_COLORS
# eval "$(dircolors -b /etc/DIR_COLORS)"

# Fixup git-bash in non login env
shopt -q login_shell || . /etc/profile.d/git-prompt.sh

snowdreams1006@home MINGW64 /e/git
# 刷新配置文件,使其立即生效
$ source ./etc/bash.bashrc

snowdreams1006@home MINGW64 /e/git
# 移除 `tree` 別名,適用於命令行方式設置而不是文件設置
$ unalias tree

snowdreams1006@home MINGW64 /e/git
# 運行 `tree` 命令,確保已經無法通過別名方式調用系統的 `tree.com` 命令
$ tree
bash: tree: command not found

git-bash-tree-bin.gif

真的成功添加了 tree.exe 命令,明顯和 cmd 自帶的 tree.com 命令不一致.

snowdreams1006@home MINGW64 /e/git
$ cd /g/sublime/test

snowdreams1006@home MINGW64 /g/sublime/test
# 擴展命令 `tree` 幫助信息
$ tree.exe --help
usage: tree [-adfghilnpqrstuvxACDFNS] [-H baseHREF] [-T title ] [-L level [-R]]
        [-P pattern] [-I pattern] [-o filename] [--version] [--help] [--inodes]
        [--device] [--noreport] [--nolinks] [--dirsfirst] [--charset charset]
        [--filelimit #] [<directory list>]
  -a            All files are listed.
  -d            List directories only.
  -l            Follow symbolic links like directories.
  -f            Print the full path prefix for each file.
  -i            Don't print indentation lines.
  -q            Print non-printable characters as '?'.
  -N            Print non-printable characters as is.
  -p            Print the protections for each file.
  -u            Displays file owner or UID number.
  -g            Displays file group owner or GID number.
  -s            Print the size in bytes of each file.
  -h            Print the size in a more human readable way.
  -D            Print the date of last modification.
  -F            Appends '/', '=', '*', or '|' as per ls -F.
  -v            Sort files alphanumerically by version.
  -r            Sort files in reverse alphanumeric order.
  -t            Sort files by last modification time.
  -x            Stay on current filesystem only.
  -L level      Descend only level directories deep.
  -A            Print ANSI lines graphic indentation lines.
  -S            Print with ASCII graphics indentation lines.
  -n            Turn colorization off always (-C overrides).
  -C            Turn colorization on always.
  -P pattern    List only those files that match the pattern given.
  -I pattern    Do not list files that match the given pattern.
  -H baseHREF   Prints out HTML format with baseHREF as top directory.
  -T string     Replace the default HTML title and H1 header with string.
  -R            Rerun tree when max dir level reached.
  -o file       Output to file instead of stdout.
  --inodes      Print inode number of each file.
  --device      Print device ID number to which each file belongs.
  --noreport    Turn off file/directory count at end of tree listing.
  --nolinks     Turn off hyperlinks in HTML output.
  --dirsfirst   List directories before files.
  --charset X   Use charset X for HTML and indentation line output.
  --filelimit # Do not descend dirs with more than # files in them.

snowdreams1006@home MINGW64 /g/sublime/test
# 原生 `tree.com` 幫助信息
$ winpty tree.com /?
卷 軟件 的文件夾 PATH 列表
卷序列號為 000000CA 223E:7300
E:\GIT\?
無效的路徑 - \GIT\?
沒有子文件夾  

雖然原生 cmd 自帶的 tree.com 命令也能打印出目錄結構樹,但是和擴展的第三方 tree.exe 命令相比,可配置的選項實在太少,難怪固執少年會執意擴展 tree 命令.

懶人直達

如果想要在 git bash 命令行中調用 tree 命令,總結了下列幾種方法.

注意: 從上到下逐漸復雜,根據自己的情況自行選擇.

  • winpty tree.com : 直接調用 cmd 內置 tree.com 命令.
  • winpty cmd //c tree : 通知 cmd 調用 tree 命令.
  • 安裝 Git For Windows 開發版,Pacman -S tree 安裝 tree 命令,然后執行 tree 調用.
  • 下載 已編譯好的 tree.exe 文件到 git bash 安裝目錄下的 /usr/bin 目錄,然后執行 tree 命令.

回顧總結

Git 本身並不支持 Windows 系統,Git For Windows 團隊為了移植到 Windows 平台,付出了很多努力,最直觀的感受就是提供了 Git For Windows 軟件.

由於 Git for Windows 的出色工作得到 Git 的官方認可,現在默認下載的 Git 就是來源於 Git for Windows.

Git 底層是運行在類 linux 系統的,這種差異必然需要 WindowsLinux 的中間處理層進行轉換.

因此,Git for Window 背后的技術中涉及到大量的 GNU 自由軟件操作系統和 WSL (Windows Subsystem for Linux) 的相關代碼.

正是由於背后千絲萬縷的聯系,為我們擴展 git bash 命令行提供了一些思路.

基於 Cygwin 系統進行擴展,安裝完整的操作系統,模擬出 linux 運行環境,在 Windows 上也能找到 linux 的感覺.

當然,Cygwin 由於比較完整,體積也相當大,所以在此衍生出 MSYS2MinGW 操作系統.

殊途同歸,他們的底層架構有些不同,但目的是一致的,都是在 Windows 上找到 Linux 的感覺,並且他們的終端命令行幾乎都是 mintty .

在終端中調用各自的包管理工具即可輕松擴展第三方命令,此外,由於他們大多數都有 c 編譯環境,因此也可以選擇重新編譯安裝.

所以 git bash 命令行看起來下像是 git 官方支持,其實卻是由 Git for Windows 組織獨立維護的開源項目.

默認 Git for Windows 沒有提供包管理工具,開發版卻默認集成了 MSYS2 環境.也就是說我們可以用 Pacman 來安裝 tree 命令.

最后稍微總結本文知識要點:

  • git bash 命令行並不能完全替代 cmd 命令,兩者互補才能相得益彰.
  • git bash 命令行中調用 cmd 程序需要通過 winpty 調用,比如 winpty tree.com
  • git bash 默認安裝程序無包管理工具等高級功能,如需擴展自定義命令應該下載Git for Windows SDK.
  • git bash 環境兼容 MSYS2 ,MinGW ,Cygwin 等系列自由軟件,其他類似系統的 tree.exe 可能並不支持.

好了,說了這么多,小伙伴們 get 到如何在 git bash 使用(擴展) tree 命令了嗎?

如有疑問,歡迎留言告訴我!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM