如何使 WSL2 的 cd 命令接受 Windows 路径?

如何使 WSL2 的 cd 命令接受 Windows 路径?

我是一名 WSL 皈依者,来自 cygwin。 cygwin 所做的一件巧妙的事情就是接受 unix命令中的 Windows 文件路径cd。当然,大多数 Windows 路径都包含\,这是 unix 中的特殊字符,但只要您对其进行转义,则cding 到 Windows 路径就会按预期工作cd 'C:\Program Files'C改变你的D目录为/cygdrive/c/Program Files1

WSL 的情况并非如此。cd 'C:\Program Files'打印一条错误消息:cd: no such file or directory: C:\Program Files

我喜欢 cygwin 的功能。cd当我在 WSL 中使用时,有没有办法获得相同的行为?

解决方案可以采用以下形式:安装第 3 方工具(即sudo apt install <x>)、创建别名、在我的 shell 中启用某些bind或或编写我自己的 shell 脚本。bindkey只要它允许我使用unixWindows 路径作为cd参数,我会很高兴。


附加信息

我的发行版是 Ubuntu。我使用 zsh 作为主 shell,但在 bash 中编写 shell 脚本。理想情况下,该解决方案对两者都适用,但如果不可能,我想要一个 zsh 解决方案。

我发现这个相关问题可能会帮助人们尝试回答我的问题:Cygwin:轻松从 CD 到 Windows 路径

对于那些不使用 WSL 但想要提供帮助的人,值得了解的是 WSL 附带了一个名为 的命令wslpath这是我发现的最接近官方文档的东西,这是它的使用输出:

➜  ~ wslpath
wslpath: Invalid argument
Usage:
    -a    force result to absolute path format
    -u    translate from a Windows path to a WSL path (default)
    -w    translate from a WSL path to a Windows path
    -m    translate from a WSL path to a Windows path, with '/' instead of '\'

EX: wslpath 'c:\users'

我已经在我编写的另一个脚本中使用此命令,从 WSL 命令行打开 Windows 中的目录/文件:

➜  ~ cat ~/bin/open
#! /bin/bash
set -x

arg="$*"
explorer.exe "$(wslpath -w "$arg")" # take a unix path and open it in Windows

1:cygwin的/cygdrive/c/路径与WSL的路径同义/mnt/c

答案1

Cygwin 在 Windows 库接口之上模拟 Unix/Linux 库接口。让 Unix 与 Windows 共存需要付出很大的努力,特别是在处理文件名的基本库函数中将路径转换为 ​​Windows 路径。该代码特定于 Cygwin,旨在使大多数类 Unix 程序在 Windows 环境中运行。因此,当该代码看到类似 的路径时,它不会翻译它,而不是尝试打开当前目录中c:\somefile调用的文件。c:\somefile

WSL 旨在提供一个在 Windows 系统内部运行的完整 Linux 环境,而不是直接在硬件之上运行。让 Linux 程序运行需要付出很多努力,包括支持文件名中的冒号。因此,当该代码看到类似 的路径时c:\somefile,它会确保将其视为c:\somefile当前目录中的路径。

因此,WSL 程序通常无法支持 Windows 路径。可以访问 UNC 路径,但需要安装

但是,如果您不介意它们不支持边缘情况(例如包含冒号或反斜杠的某些文件名),您可以为特定命令添加翻译代码。

要自定义cd命令(它是 shell 内置命令),请编写自己的函数,该函数在调用 shell 内置命令之前执行所需的操作。这是未经测试的代码,当使用单个参数调用.zshrc时,它可以识别 Windows 路径:cd

function cd {
  emulate -L zsh
  if [[ $# -eq 1 && ( $1 == [A-Za-z]:\\* || $1 == \\\\*\\* ) ]]; then
    set -- "$(wslpath "$1")"
  fi
  builtin cd "$@"
}

注意,如果路径包含空格或其他特殊字符,需要用引号引起来。特别是,您不能在 后粘贴任意路径cd。 (如果唯一的特殊字符是单个空格,则可以连接参数。但这不起作用,例如,对于包含两个连续空格的路径。)要更改到路径位于剪贴板中的目录,请使用类似

alias cdp='cd "$(powershell.exe -c Get-Clipboard)"'

答案2

如果您只想识别类似 Windows 的路径cd/ zsh 内置程序,您可以将它们重新定义为:pushd

cd pushd() {
  emulate -L zsh
  set -o extendedglob
  local match
  if [[ $argv[-1] = (#bi)([a-z]):(|[\\/]*) ]] argv[-1]=/mnt/$match[1]:l$match[2]:gs:\\:/
  builtin $0 "$@"
}

答案3

这是不可能的。在 Unix 上,cd内置于 shell 中(必须这样才能工作)。您使用的 zsh 和 bash 是从 Ubuntu 附带的,与真实 Linux 系统上的相同。

Unix 系统会将其视为单个相对目录;也就是说,这样做cd 'C:\Program Files'将在当前目录下查找名为 的目录C:\Program Files,该目录是 Unix 上有效的简单路径组件。 (我应该指出,这在 Windows 上不是有效的简单目录或路径组件。)因此,您在 WSL 上要求的内容与在 Linux 上要求的内容不同。

如果您的问题是,“为什么 WSL 中的 Ubuntu 没有这种特殊情况?”那么答案是 Ubuntu 和其他 Linux 发行版不从事发布 WSL 发行版的业务,它们从事发布真正的 Linux 系统的业务,并且在其代码中具有奇怪的 Windows 特定行为是一个巨大的维护负担(您可以从维护 Windows 或 Cygwin 中的 Git 工具的工作量中可以看出这一点)。

此外,在 WSL 下工作的人通常希望事情与 Linux 相同,每次偏离都会被视为错误。仅仅因为您不想使用包含冒号和反斜杠的奇怪路径名来引用当前目录下的目录,并不意味着其他人不会这样做,并且许多 Unix 工具都有测试和假设,至少,任意非-slash,非NUL UTF-8可以存储在文件系统中,因此进行此更改会破坏许多Unix工具。

答案4

我只是用./mnt/(drive name)/Windows/path/to

例如,如果我想更改为Windows路径D:\test,那么我会cd /mnt/d/test在使用WSL时写入。

相关内容