Files
T

7.1 KiB
Raw Blame History

slug, title, description, toc, authors, tags, categories, series, date, lastmod, featuredVideo, featuredImage, draft, enableComment
slug title description toc authors tags categories series date lastmod featuredVideo featuredImage draft enableComment
Windows Git Bash 上使用 ADB 的問題 Windows Git Bash 上使用 ADB 的問題 true
awin
windows
terminal
System
Windows
2026-08-20T00:00:00 2026-08-20T00:00:00 false true

Windows Git Bash 上使用 ADB 的路徑轉換問題

在 Windows 的 Git Bash 裡使用 ADB 時,可能會遇到一個讓人摸不著頭緒的問題:明明輸入的是正確 Android pathADB 收到的卻像是 Windows path。

例如,要把目前目錄的 1.txt 傳到 Android 裝置:

adb push 1.txt /data/local/tmp/

這條命令裡其實同時存在兩個檔案系統:

1.txt               Windows 本機檔案
/data/local/tmp/    Android 裝置內的目的地

對 ADB 來說,兩者的意義很清楚;但 Git Bash 背後的 MSYS2 runtime 只看得到命令列字串。它看到 /data/local/tmp/ 這種以 / 開頭的參數時,可能會以為這是本機 POSIX path,於是在啟動 Windows 原生的 adb.exe 前,先把它轉成 Windows path。

結果,一個原本屬於 Android 的 path,就這樣被「好心辦壞事」地改寫了。

Git Bash 為什麼要自動轉換 path?

Git Bash 提供類 Unix 的操作環境,使用的 path 長得像這樣:

/c/Users/<username>/Downloads/1.txt

Windows 原生程式通常期待的是:

C:\Users\<username>\Downloads\1.txt

為了讓 Git Bash 可以順利呼叫 Windows 程式,Git for Windows 所附的 MSYS2 runtime 會檢查傳給原生 .exe 的參數,並嘗試將 POSIX path 自動轉成 Windows path。

Git Bash                         Windows 原生程式

/c/Users/me/file.txt
          |
          | MSYS2 path conversion
          v
C:\Users\me\file.txt  ------->  adb.exe、subl.exe、其他 CLI

對大部分 Windows CLI 而言,這項功能非常實用。問題是,MSYS2 無法知道某個 / 開頭的參數究竟代表:

  • Windows 本機檔案的 POSIX 表示法;或
  • Android、Docker、遠端主機等另一個系統內的 path。

當兩者長得一樣,自動判斷就可能出錯。

MSYS_NO_PATHCONV 是什麼?

Git for Windows 提供 MSYS_NO_PATHCONV,用來停用傳給 Windows 原生程式的 POSIX-to-Windows path conversion。

MSYS_NO_PATHCONV=1 adb push 1.txt /data/local/tmp/

設定後,/data/local/tmp/ 會原樣傳給 adb.exe,不再被改寫成本機 Windows path。

它的行為可以整理成:

沒有設定 MSYS_NO_PATHCONV
    -> 使用預設的自動 path conversion

設定 MSYS_NO_PATHCONV=1
    -> 停用自動 path conversion

需要特別注意:MSYS_NO_PATHCONV=1 不是開啟轉換,而是關閉轉換。若要恢復預設行為,應該移除這個環境變數:

unset MSYS_NO_PATHCONV

不要把 MSYS_NO_PATHCONV=0 當成「重新開啟轉換」;這是一個是否存在的停用開關,不是一般的 01 Boolean 設定。

不要全域停用 path conversion

最直接的做法看起來是把下面這行寫進 shell 設定檔:

export MSYS_NO_PATHCONV=1

但這會影響之後啟動的所有 Windows 原生程式。

例如,原本可以在 Git Bash 使用 POSIX path 呼叫 Sublime Text

subl.exe /c/Users/<username>/notes.txt

預設情況下,MSYS2 會將參數轉成正確的 Windows path。若全域停用轉換,subl.exe 會直接收到 /c/Users/...;Windows 原生程式可能將它視為目前磁碟機根目錄下的 c\Users\...,最後開啟錯誤的位置。

因此,真正需要的不是「整個 Git Bash 都不要轉換」,而是「只有呼叫 ADB 時不要轉換」。

正確做法:只替 ADB 停用轉換

可以為 ADB 建立一個 shell wrapper

adb() {
  MSYS_NO_PATHCONV=1 command adb.exe "$@"
}

如果使用 Zsh,將它加入 ~/.zshrc,再重新載入:

source ~/.zshrc

如果使用 Bash,則加入 ~/.bashrc

source ~/.bashrc

這個 wrapper 做了三件事:

  1. 讓輸入的 adb ... 先進入 shell function。
  2. 只替這次執行設定 MSYS_NO_PATHCONV=1
  3. command adb.exe "$@" 呼叫真正的 ADB,並完整保留所有參數。

如此一來,影響範圍只限於 ADB

一般 Windows CLI
    -> 維持預設 path conversion

adb.exe
    -> 只在這次呼叫停用 conversion
    -> Android path 保持原樣

停用轉換後,本機絕對路徑怎麼辦?

停用 path conversion 也會帶來另一個問題。以下命令的第一個 path 是 Windows 本機檔案:

adb push /c/Users/<username>/Downloads/1.txt /data/local/tmp/

wrapper 會讓所有參數都保持原樣,因此 adb.exe 收到的本機來源仍是:

/c/Users/<username>/Downloads/1.txt

這不是 Windows 原生 path。此時應使用 cygpath,主動將本機來源轉換成 Windows 格式:

adb push "$(cygpath -w /c/Users/<username>/Downloads/1.txt)" /data/local/tmp/

其中:

cygpath     在 POSIX 與 Windows path 格式之間轉換
-w          輸出 Windows 格式
$(...)      執行括號內的命令,並用輸出取代這一段
"..."       確保含有空白的 path 仍被視為單一參數

shell 展開後,實際傳給 ADB 的命令概念上會變成:

adb.exe push "C:\Users\<username>\Downloads\1.txt" /data/local/tmp/

如果來源是目前目錄下的相對路徑,就不需要額外處理:

adb push 1.txt /data/local/tmp/

相對路徑 1.txt 對 Git Bash 與 Windows 原生程式而言,都會以目前工作目錄為基準,因此通常可以直接使用。

判斷原則

遇到 path conversion 問題時,可以先問兩個問題:

這個 path 屬於哪一個檔案系統?
    |
    +-- Windows 本機
    |      |
    |      +-- POSIX 絕對路徑:用 cygpath -w 主動轉換
    |      +-- 相對路徑:通常可直接使用
    |
    +-- Android/遠端系統
           |
           +-- 必須保持原樣,不可被 MSYS2 當成本機 path 轉換

MSYS_NO_PATHCONV 並不是越常設定越好。它適合用在「目標程式有自己的 slash path 語意」的單次命令,例如 ADB;不適合成為整個 shell 的全域預設。

結論

這個問題的根源不在 ADB,也不在 Android,而是同一條命令同時跨越了三個世界:

Git Bash 的 POSIX path
          |
          v
Windows 原生 adb.exe
          |
          v
Android 裝置內的 path

MSYS2 的自動轉換原本是為了打通 Git Bash 與 Windows,卻無法辨認 Android path。正確解法是縮小例外範圍:保留全域預設轉換,只在呼叫 ADB 時設定 MSYS_NO_PATHCONV=1;若本機來源使用 POSIX 絕對路徑,再以 cygpath -w 明確轉成 Windows path。

簡單來說:本機 path 主動轉換,Android path 保持原樣,而且例外只套用在真正需要的命令上。

參考資料