将setCaseSensitiveInfo递归应用于所有文件夹和子文件夹

42
我想要配置我的dotnet core项目(在Windows中)为"大小写敏感",以便它的行为与我的生产服务器(Linux)一致。 我已经找到了这样做的方法
fsutil.exe file setCaseSensitiveInfo "C:\my folder" enable

该函数存在的问题在于它不是递归的:
引用: 特定文件夹上应用的大小写敏感标志仅影响该文件夹。它不会自动地被该文件夹的子文件夹继承。
因此,我正在尝试构建一个PowerShell脚本,可以将其递归地应用于所有文件夹和子文件夹。
我已经尝试过类似的搜索并只修改命令行,但我似乎找不到正确的关键词。这是我找到的与此类似的示例中最接近的的一个。

1
(没有Windows 10测试)(gci -Recurse -Directory).FullName | % {fsutil.exe file setCaseSensitiveInfo $_ enable} - Robert Dyjas
@robdy 这是正确的答案。谢谢。它回答说“setCaseSensitiveInfo是无效参数”,但这是Window7的问题...我用(gci -Recurse -Directory).FullName | % {echo $_}测试了你的脚本,它完美地工作。 - Xavier Peña
3
不幸的是,尽管上述方法曾经有效,但微软现在已经向fsutil添加了一个“功能”,它将不再允许您在非空目录上设置大小写敏感性。现在,当您尝试将上述方法应用于具有子目录的目录时,您将会得到大量以下错误信息:错误:该目录不为空。 - eric.green
5个回答

59

正确的代码:

(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}

解释:

注意: 回答中的代码假定您位于目录树的根目录下,并且您想针对其内部的所有文件夹运行 fsutil.exe,正如在评论中指出的一样(感谢@Abhishek Anand!)

Get-ChildItem -Recurse -Directory 将给您所有文件夹的列表(递归方式)。

由于您想要传递它们的完整路径,因此可以使用 .FullName[1] (或更自解释的 | Select-Object -ExpandProperty FullName) 访问它们的路径。

然后使用 ForEach-Object 多次运行 fsutil.exe。 当前文件的 FullName 可以通过 $_ (表示 ForEach-Object 中当前对象) 来访问。[2]

提示:

如果您想要更多跟踪当前正在处理的内容,可以添加以下内容将当前处理的文件路径写入控制台: ; Write-Host $_ (分号 ; 是为了与 fsutil 调用分开),正如在评论中指出的一样(感谢Fund Monica's Lawsuit !)


[1] .FullName 符号仅适用于 PowerShell 3.0 及更高版本,如果存在使用低版本的可能性,则建议使用 Select-Object -ExpandProperty FullName

[2] $_$PSItem 的别名


4
请先使用 cd 命令进入需要变为区分大小写的目录根目录。 - Abhishek Anand
2
如果您想更深入地了解问题发生的位置,可以在 { 后面添加 echo $_;,它将在执行任何操作之前打印出当前正在操作的内容。 - anon
我收到了“在此处意外出现.FullName”的错误信息,这是什么问题? - imbr
请检查 Get-ChildItem 的输出。可能对于您运行它的目录来说是空的。 - Robert Dyjas
2
两件事:使用(Get-ChildItem foldername -Recurse -Directory).Fullname | ForEach-Object {fsutil file setCaseSensitiveInfo "$_" enable},并将_foldername_替换为您要使用的文件夹。其次,请确保打开管理员Shell,此外,我发现如果文件夹已经包含内容,则似乎不起作用;我会收到“目录不为空”的错误消息。 - theking2

6
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {if (-Not ($_ -like '*node_modules*')) { fsutil.exe file setCaseSensitiveInfo $_ enable } }

我修改了@robdy的代码,以允许排除node_modules。你可以将上面的“node_modules”替换为任何要排除包含它的文件路径。
如果您正在使用npm,则可能希望排除node_modules。 @robdy的答案很好,但即使我没有安装该包,它也需要几分钟的时间遍历每个单独的节点包文件夹;鉴于这是一个人们可能经常运行的东西,因为目录可能随时添加,并且由于您可能不会修改node_modules中的任何内容,因此排除它似乎是合理的。

2
请注意,在区分大小写的目录下创建的子目录是区分大小写的,因此您将永远不需要在该目录上再次运行此脚本。 - eric.green
node_modules 是我需要使用这个命令解决的有问题的目录。 - Citricguy
2
@eric.green我认为这并不是正确的。来自微软:"请注意,每个目录的大小写敏感标志不是继承的;在大小写敏感的目录中创建的目录本身不会自动变得大小写敏感。您必须显式地将每个目录标记为大小写敏感。" - Aleksandr Hovhannisyan
原来我的Jenkins构建问题是由node_modules中的一个库引起的,在Windows上被隐藏了,但在Linux系统上引发了我的Jenkins Pipeline构建失败,由于类型敏感性,我不建议忽略node_modules中的大小写。 - JesseBoyd

5
使用Cygwin和bash shell,您可以这样做:
$ find $THEDIR -type d -exec fsutil file setCaseSensitiveInfo "{}" enable \;

看起来,Windows可以很好地处理find命令输出的 '/' 字符。


4
在我的情况下,在使用fsutil工具之前,我必须先启用Linux子系统。所以我的步骤如下:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

然后重新启动,在执行这个方案时,遵循@robdy的建议:

(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}

如果调用fsutil命令的目录必须为空,那么你们如何运行这些命令? - vincenzoml
@vicenzomi 目录不需要为空。实际上,该命令只是递归地修改子目录的目录属性,控制该目录的大小写敏感配置。 - Fede Garcia
1
在 Windows 11 上,显然目录必须为空。请参见 https://pastebin.com/cMQrRjXU。为了克服这个问题,我创建了一个空文件夹,设置了区分大小写的标志,然后将其他目录的内容复制到其中。新目录会继承区分大小写的标志。 - vincenzoml

3
在 Windows 11 上,其他答案都不正确,因为 fsutil 要求目录不为空。为了克服这个问题,我创建了一个新的空目录,使用 fsutil file setCaseSensitiveInfo 命令设置了新目录的大小写敏感标志,然后将其他目录中的文件移动到新目录中。这样做是有效的,因为在移动时会重新创建目录,并且新目录会继承大小写敏感标志。

它是否也适用于启用了 setCaseSensitiveInfo 的新创建目录内的子目录? - Amit Joshi
是的,它有效,如果您创建一个新目录,则标志会被继承。 - vincenzoml
我使用了 Github,因此只需删除文件夹中的所有内容,启用大小写敏感,并丢弃文件夹中所有更改,这似乎起作用了。但是 Github 和 VSCode 仍然没有识别到该更改。已通过 git config core.ignorecase false 来修复 git 方面的问题。 - Akaisteph7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接