Powershell: 在 Windows 中默认使用正斜杠

创建于 2019-09-11  ·  49评论  ·  资料来源: PowerShell/PowerShell

新功能/增强功能摘要

PowerShell 的目标是跨平台,但我在跨 Windows 和 Linux 的路径上运行时遇到了很多问题。 我了解在可预见的将来需要在 Windows 中支持\ ,但我至少希望 Windows 和 *nix 上的默认路径字符相同,大概是通过将默认路径分隔符设置为/ 。 当前的替代方案是强制用户在其路径中使用-replace "\\", "/"自己规范化路径。

Issue-Enhancement Resolution-By Design

最有用的评论

我认为如果路径完成使用在完成文本中明确出现的路径分隔符会很好,如果没有,则默认为平台本机分隔符。

所以在 Windows 上, c:\w完成到c:\Windows\并且c:/w完成到 'c:/Windows/'。

我认为这将涵盖大部分烦恼而不需要配置选项,并且实际上更可取,因为您有时可能出于任何原因需要其他形式。

所有49条评论

当前的替代方案是强制用户规范化路径

PowerShell 已经为您完成了这项工作,您无需规范化路径。
PowerShell 在这里非常用户友好 - 用户可以使用他们喜欢的斜线,无论平台如何。
最佳做法是避免使用文字路径并使用路径 cmdlet。

最佳做法是避免使用文字路径并使用路径 cmdlet。

@iSazonov是的,也不是。

当然,如果您正在组合路径段,则可以使用路径 cmdlet。 但是,如果您正在编写一个引用具有多个段的相对路径的脚本,并且您打算让您的脚本跨平台工作,那么您不会这样做。

在 Windows 上的 PowerShell 7 预览版 3 中,制表符补全使用反斜杠完成路径。 这是我认为我们做错的地方,因为 PowerShell 是跨平台的。 至少应该有一个选项来选择要在 Windows 上使用的目录分隔符作为制表符完成的一部分: [System.IO.Path]::DirectorySeparatorChar[System.IO.Path]::AltDirectorySeparatorChar 。 鉴于我们今天所处的位置,我怀疑大多数做任何跨平台工作的人都希望默认情况下在 Windows 上使用选项卡完成路径以使用AltDirectorySeparatorChar ,但据我所知,没有办法做到这一点.

@chriskuech :除了路径的制表符完成之外,是否还有其他地方您觉得AltDirectorySeparatorChar没有被使用,您希望可以选择使用它而不是DirectorySeparatorChar ? 我什么都想不出来。

@KirkMunro ,您是说今天有一种(至少部分实现)方式来规范化 PowerShell 中的路径? 如果是这样,它可以在最新的 6.x 上运行吗? 我遇到问题的用例是自动变量和*-Path命令。

@iSazonov ,建议的解决方案不适用于我的场景,因为我在 Windows 上生成了路径列表,在 Linux 上生成了路径列表,然后尝试比较它们,但由于分隔符而失败。

自动变量始终缺少尾随目录分隔符,因此 PowerShell 完美地允许使用文字创建路径。 前任:

$RepoRoot = "$PSScriptRoot/../.."
$SourceRoot = "$RepoRoot/src"
$BuildRoot = "$RepoRoot/.build"

我认为这比

$RepoRoot = Join-Path $PSScriptRoot "../.."
$SourceRoot = Join-Path $RepoRoot "src"
$BuildRoot = Join-Path $RepoRoot ".build"

所以我希望它可以在未来工作,即使不是默认的。

@chriskuech我的个人习惯变成了这样:

$SourceRoot = $RepoRoot | Join-Path -ChildPath 'src'

它更清晰一些,但它并不完美。

Join-PathAdditionalChildPath接受字符串数组。

@chriskuech感谢您提供更多信息。

我并不是说 PowerShell 部分支持路径的规范化。 我只是说我个人不喜欢在 Windows 上默认使用反斜杠,在 Linux 或 macOS 上默认使用正斜杠。

如果我可以调整一些设置来更改它,以便默认情况下即使在 Windows 路径上也使用正斜杠,我会进行更改,这是我认为可能有机会使跨平台 PowerShell 工作更容易的地方。 Join-Path也使用[System.IO.Path]::DirectorySeparatorChar作为路径分隔符。 理想情况下,如果在编写脚本时设置了所需的路径分隔符(因为无论我们选择在哪个平台上编写脚本,我们都应该能够轻松地以我们想要的方式编写脚本),这将反映在两个选项卡完成中路径和Join-Path也是如此。

除了这些个人需求,我想知道Compare-Path cmdlet 是否有用。 它可以规范化路径分隔符,甚至可以通过在比较之前解析相对路径来将绝对路径与相对路径进行比较,如果其中一个路径是绝对的。

好吧,我们确实在Convert-PathResolve-Path中得到了 _platform-specific_ 规范化:

PS> Convert-Path C:/Windows
C:\Windows # normalized to Windows-native "\"

因此,也许作为引入Compare-Path cmdlet 的替代方案,可以扩展Convert-PathResolve-Path以支持-UseSlash开关(名称可协商)。

另外,作为补充,Kirk 建议的在 Windows 上使用/的选择加入偏好机制也适用于Convert-PathResolve-Path (除了制表符补全和Join-Path )。

目前的问题是Convert-PathResolve-Path仅适用于 _existing_ 路径,但这本身就值得改变,正如@jaykul很久以前建议的那样 - 请参阅#2993

我认为如果路径完成使用在完成文本中明确出现的路径分隔符会很好,如果没有,则默认为平台本机分隔符。

所以在 Windows 上, c:\w完成到c:\Windows\并且c:/w完成到 'c:/Windows/'。

我认为这将涵盖大部分烦恼而不需要配置选项,并且实际上更可取,因为您有时可能出于任何原因需要其他形式。

@lzybkr ,我喜欢这个想法,同时考虑到我忽略了基于配置/首选项变量的解决方案的担忧:范围问题; 使用通常的 _dynamic_ 作用域,对路径分隔符做出固定假设的代码可能会中断(这与 https://github.com/PowerShell/PowerShell-RFC/issues/7 的回声有关)。

@lzybkr以及何时使用两个斜杠? C:\Program Files/A -> ?

如此多的选项 - 随机,交替每一个,总是正斜杠 b/c 它是一个真正的路径分隔符,等等。

更严重的是,可能只选择最后一个使用的,可能是用户输入的,而其他人可能不是。

@lzybkr :不过有一个问题:

如果您开始_没有_路径分隔符,为了引用_当前目录_中的文件/文件夹,PowerShell 将不得不为您做出选择,至少基于扩展为.\<filename>./<filename>的当前完成算法.\<folder>\./<folder>/ ,适用于平台。

对于 _files_ 作为 _arguments_,我们可以通过将fil扩展为 $ file #$ 来回避这个问题,例如(没有.\ / ./前缀)。

然而:

  • 对于 _executables_ ,如果确实要执行位于当前目录中的脚本,自动添加的.\ / ./前缀是一种有价值的便利。

  • 对于 _directories_,类似地,扩展为带有 _trailing path separator_ ( <folder>\<folder>/ )的东西也很有价值。

在这两种情况下,都没有用户操作来暗示首选分隔符。

也就是说,也许解决方案是:如果你想控制分隔符,_manually start with_ ./.\并让制表符完成尊重这一点。

此问题已标记为已回答,并且1 天没有任何活动。 它已因家政目的而关闭。

@iSazonov :这并没有真正得到回答,应该重新打开以允许正在进行的讨论继续解决这个问题。 OP 甚至没有机会回答向他提出的问题。

我想我把所有的问题都给了我,但如果我没有,请告诉我。 我也不确定为什么这个问题被关闭了。 这并不是一个讨论线程,而是一个功能请求。

手头的根本问题:

  • 默认情况下,跨平台工具是否应该具有非跨平台行为?
  • 如果是这样,是否有办法以“跨平台”模式全局运行 PowerShell?

我认为强迫开发人员使用 cmdlet 手动规范化字符串是绝对错误的举动。 我没有看到默认使用/会在 Windows 上导致问题的任何场景,因为如前所述,PowerShell 非常适合处理这两种斜线。 除非任何人都可以提供可能导致错误的令人信服的情况,否则为什么不默认使用/呢? 也许这个问题需要转移到 RFC。

随着越来越多的人迁移到云端,越来越多的人在 Windows 上开发 PowerShell 代码并在 Linux 上运行。 未来肯定会出现一个点(如果还没有过去的话),喜欢真正跨平台行为的用户数量超过任何强烈希望在 Windows 上保留\的用户数量。

@chriskuech :我的错,我没有专门向你提出这个问题。 我想知道您是否觉得Conpare-Path cmdlet 会帮助您。 抛开这个问题不谈,我也希望看到标准化选项。

@KirkMunro我不确定Compare-Path会有所帮助,因为在原始用例中(比较Linux和Windows上的路径),根文件系统是不同的,所以我必须调用Resolve-Path -Relative 。 那时,比较用例只是一个单行: | ? {($_ -replace "\\", "/") -in $ExpectedPaths}

但是,我很犹豫是否支持任何基于 cmdlet 的解决方案,因为它不能解决根本问题,并且要么不允许路径的字符串插值,要么需要对每个路径字符串定义进行代码更改。 具体来说, Compare-Path不会用混合斜杠修复我所有记录的路径。

@KirkMunro @mklement0这个问题没有被锁定,每个人都可以拉评论。
我们有很多问题没有新的评论和进展。 开放状态已经失去了意义。
作为维护者,我打算更加严格,以鼓励讨论成为更严格的规范,这些规范很容易变成 PR。
至于这个问题,它变成了无限 - 初始请求是“在 Windows 上使用正斜杠”,然后是“比较路径”。 接下来是什么? 远程? 它可以继续,但将关闭。
虽然上面只有一个来自 Jason 的真正提案(以提高完成度),但我们可以打开一个跟踪问题并通过真正的 PR 将其关闭。

需要明确的是,问题仍然是“在 Windows 上使用正斜杠”。 “比较路径”仅作为(多个)激励示例之一提出。

提议
实现真正的跨平台行为,其中路径分隔符在所有平台上默认为/ ,除非用户使用制表符完成已包含\的路径。 我希望这暂时作为一项实验性功能被隐藏,但我至少应该能够在我的代码中启用“最大化跨平台行为”功能,以优化针对 Linux 的 Windows 开发人员的开发体验。

如果这是不合理的,我想知道为什么以及当 PowerShell 设计跨平台分歧时是否有文档指导。

@iSazonov :PS repo 的维护者不应该不经讨论就对用户问题不屑一顾。 您最初没有花时间了解OP的需求就回复了,将问题标记为已回答,但该问题没有作为问题发布,而是作为功能请求发布,从讨论中可以看出很明显没有回答”。

开放状态已经失去了意义。

谁说? 这绝对不是真的。 一个开放的问题是开放的,一个封闭的问题是关闭的。 这两个区别的含义非常明确。 如果它们是我自己的并且我想回去检查一些东西,我只会查看已关闭的问题。 在极少数情况下,我可能会搜索已关闭的问题以讨论某个主题。 但是我在问题上的 90% 或更多时间都在未解决的问题上,这是应该的。 唯一模糊两者之间界限并使开放问题失去意义的事情是在解决它们之前立即关闭它们,就像你对这个问题所做的那样。

(讨论)可以继续,但将被关闭。

基于这种管理问题的方法,您正在迫使人们失去开放和封闭之间的区别,以至于他们必须搜索所有问题而不是关注开放问题,这意味着检查 2K 开放问题和 4K 封闭问题与他们相关的讨论,而不是仅仅关注未解决的问题。 这是一个破碎的、有缺陷的问题管理策略。

至于这个问题,它变成了无限 - 初始请求是“在 Windows 上使用正斜杠”,然后是“比较路径”。 接下来是什么? 远程?

这太荒谬了。 讨论的重点是在您为跨平台编写脚本时处理默认使用反斜杠的 Windows。 它一直专注于该主题。 你试图让它听起来像是根本没有集中注意力。

@iSazonov ,我同意有太多未解决的问题; 然而,有太多未决问题的事实并不意味着我们应该对新问题不屑一顾并过早地停止对话。 我们必须继续鼓励反馈,并愿意在未解决的问题中讨论有关 PowerShell 的问题,并且只有在问题真正解决后才关闭它们。 必须以不同的方式处理未决问题的数量。

忠实的 linux 用户?难以理解的建议。
你可以说服微软。 要求他们使用反斜杠作为系统文件路径。

我想在这里补充一下,有些用例需要带有正斜杠的文字路径,即使在 Windows 上也是如此。

我只是在编写一个脚本,我在其中使用 .net API 来操作和创建 zip 档案。 使用此 API 将条目添加到 zip 文件:

    [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
        $zip, $file, $entry,
        [System.IO.Compression.CompressionLevel]::Optimal
    ) > $null

在这种特殊情况下,$entry 是 zip 存档中的路径。 如果我只是通过各种路径 cmdlet 返回的 windows 路径,地球上的每个 zip 实用程序都会发出警告,提示我的 zip 文件有错误的斜杠。

同样作为一个长期的 linux 用户和开发人员,我喜欢 powershell,并且我在学习它时获得了很多乐趣。 我在通过 ssh 到 powershell 7 中使用我的新 windows 服务器核心也很开心,并且我已经发布了与 linux 上的 powershell 完美配合的脚本。 我很惊讶它的效果如何。 事实上,对于一些我想要跨平台的程序/脚本,powershell 将是我的首选。

但看到我所有的制表符完成都被反斜杠重写,我仍然感到难过。

我一直在 Windows 上使用 /users/foo/somefile 之类的路径,这就是我想要使用的。

大多数 Windows API 都支持正斜杠。 我意识到有一些例外,实用程序和 API,即一些 cmd.exe 调用,但我只想在我的 $profile 中设置一些东西,以便默认情况下我的所有路径都有正斜杠,除非我明确使用反斜杠。

这对于习惯使用反斜杠的 Windows 用户和开发人员来说是无害的,因为他们根本不会使用此设置,并且默认为关闭。 当然,如果他们决定编写更多跨平台脚本和模块,他们也可能决定使用它。

我也想为我的脚本和模块设置这个设置,这样我就不会遇到像上面展示的那样的意外问题。

@iSazonov用户可以使用他们喜欢的斜线,无论平台如何。

这是否意味着我可以将 PowerShell 配置为使用正斜杠,因为这对我作为用户来说更舒服? 我想更改提示中显示的路径以及当前将正斜杠更改为反斜杠的选项卡自动完成。

@aaronfranke ,不,目前没有办法以这种方式配置 PowerShell; 我认为@iSazonov想说的是,当您手动输入路径时,您可以在\/之间自由选择(甚至可以将它们混合在一个路径中) .

考虑到通用性,应该启用一个新的路径符号而不是 / 和 ,传统符号增加跨平台转换的难度

我认为@iSazonov想说的是,当您手动输入路径时,您可以在和 / 之间自由选择(您甚至可以将它们混合在一个路径中)。

是的,它是 PowerShell 设计。

这不是对此处提出的问题的解决方案,例如在完成过程中强制替换路径分隔符,或者配置路径 cmdlet 以使用您选择的路径分隔符的能力,我们应该为他们打开单独的特定问题?

@rkitover几年前我问过这种情况(你可以找到问题),但没有任何解决方案。 这让我相信这是一个表面上的改变,尽管它需要付出很多努力。 如果你准备在这个领域投资并拉一个 PR,那么只有开启一个新的讨论才有意义。

CP/M 和克隆使用/作为选项,例如: DIR/PCMD/CECHO 。 这些是有效的命令。 如果我们到处都用/代替\ ,恐怕会发生严重的误解。

  1. 没有人再使用CP/M了。

  2. 在我的测试中,同时对选项和路径使用/在 Windows 上工作得很好。

  3. 现代工具使用-作为选项,包括 PowerShell 工具和其他 Microsoft 工具,例如 .NET。 应保留使用/作为选项以实现向后兼容性,但用户不会对现代工具产生任何混淆。

另外,我想指出正斜杠/是 Win32 文件名中的无效字符名称:

https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3

要旨
Windows 文件名的无效字符。 GitHub Gist:即时共享代码、笔记和片段。

我只想指出我开始仅在跨平台脚本等中使用正斜杠,并遇到了符号链接的问题。

例如,运行

new-item -itemtype SymbolicLink -path TestScript8.ps1 -target ./TestScript.ps1

在 Windows 上,您将无法在 Windows 上的 VS Code 中打开 TestScript8.ps1。

@markm77 ,你发现了一个 _bug_ -你可以为它创建一个新问题吗? [_更新_:见#13064]

并不是说它反对默认为/的选择加入机制, @aaronfranke ,但请注意,在少数情况下/而不是\仍然会中断Windows 上的东西; 例如:

PS> cmd /c dir C:/
Invalid switch - ""

奇怪的是,双引号路径仅有助于 _directory_ 路径 - 请参阅https://stackoverflow.com/a/43297482/45375 ,这也表明 Excel COM 自动化库不支持/

堆栈溢出
$Path = 'D:/ETL_Data/TwitchTVData.xlsx' $csvPath = 'D:/ETL_Data/TwitchTVData2.csv' # 打开 Excel 文档并拉入 'Sheet1' 工作表 $Excel = New-Object -Com Excel.Application $工作簿...

@markm77 ,您发现了一个错误 - 您可以为它创建一个新问题吗?

但这是一个 PowerShell 错误吗? 通过使用dir检查符号链接,PowerShell 使用指定的斜线创建正确的符号链接。 似乎使用错误的斜杠类型创建的符号链接可能无法在 VS Code 等应用程序中使用。 这也许也是可以理解的。

注意,通过在符号链接目标上运行convert-item来解决此问题非常容易,这具有确保符号链接指向绝对路径(可能是适当的)的额外好处。

注意,通过在符号链接目标上运行convert-item来解决此问题非常容易,这具有确保符号链接指向绝对路径(可能是适当的)的额外好处。

不合适,重装会断😞

不合适,重装会断😞

公平评论,我不重新安装(这是用于本地开发工作),并且我有一个可以随时运行的链接重新生成脚本。 join-path显然是另一种解决方案,或者更好的是new-item选项,以确保链接适合平台。

见#12797

但这是一个 PowerShell 错误吗?

虽然您可能会争辩说,在 _Windows_ 上这是一个 WinAPI 错误,但鉴于\/通常可以互换支持,但如果您执行相反的操作并通过,它绝对是类 Unix 平台上的错误基于\的路径作为-Target路径 - 在此类平台上,本机仅支持/ (只有 PowerShell 允许您将\用作另一种方法,它有自己的问题 - 请参阅#9244),并且在创建符号链接时将.\TestScript.ps1转换为./TestScript.ps1是 PowerShell 的责任。

解决此问题 - 通过使 PowerShell 规范化使用(主要)_platform-native_ 分隔符的路径 - 也将解决 Windows 上的问题。

@iSazonov ,#12797 从根本上支持 _relative_ 路径作为符号链接目标,但手头的问题是缺乏平台原生分隔符规范化,这会导致生成的符号链接损坏。

@iSazonov请参阅#13064 了解 PowerShell Core 7.1.0-preview.4 中仍然存在的问题(应该包括 #12797,对吧)?

感谢@mklement0对相关符号链接行为的彻底调查和问题的提出https://github.com/PowerShell/PowerShell/issues/13064。 我已经做了一个笔记,以进一步跟进我遇到的特定问题和这个讨论,但事实上,你似乎已经涵盖了https://github.com/PowerShell/PowerShell/issues/13064中的所有内容,并且实际上教会了我如何编写 PowerShell 测试(我是 PowerShell 新手).... 干杯!

我没有详细关注这个问题,所以如果我遗漏了什么,请原谅。 最初的问题是跨平台标准化路径分隔符(可能是正斜杠)。 @iSazonov现在关闭了这个问题。 您能否概述一下为什么您认为这不再有效,以便订阅问题关闭事件的人可以跟进?

根据https://github.com/PowerShell/PowerShell/issues/10509#issuecomment -644419471,它从来都不是有效的。

像上面@lzybkr提出的东西仍然是一个完全合理的 - 并且可能很容易 - 实现的东西; 回顾一下:

我认为如果路径完成使用在完成文本中明确出现的路径分隔符会很好,如果没有,则默认为平台本机分隔符。

然后,用户有责任避免/在 Windows 上仍然中断的 - 罕见的 - 边缘情况(见上文)。

当通过 powershell 运行 wsl bash 脚本时,这会引起真正的头痛。 喜欢:

bash .\updateTemplate.sh

这应该自动完成

bash ./updateTemplate.sh

这个问题还有其他解决方法吗? 具体来说,如果 PS 仅在 bash/WSL 上下文中使用正斜杠自动完成路径,我会完全没问题。

这个问题还有其他解决方法吗?

为 bash 创建自定义完成器。

这个问题还有其他解决方法吗?

为 bash 创建自定义完成器。

你怎么做到这一点?

我们是不是没有更多关于这个问题毫无根据地结束的讨论? 这是跨平台工作的主要烦恼。 每次我自动完成提供给跨平台工具或间接通过 wsl 提供给 Linux 工具的路径时,我必须将光标向后移动整个路径,并用斜杠单独替换每个反斜杠。 任何人都不应该以这种方式工作,它确实使 Powershell 作为命令行几乎站不住脚。

此页面是否有帮助?
0 / 5 - 0 等级