在特定目录中递归搜索名称可能包含 space(s) 的文件夹

Recursively search for folder whose name may contain space(s), in a specific directory

正如Q-title中所说,我试图找到一个名为Local State的特定目录,但它可能被某些应用程序拼写为LocalStateLocal State,任何人它肯定存在于 %USERPROFILE% 内的每个 Apps 文件夹中,我正在尝试列出它。

现在我不得不写两行,其中一行用于查找 LocalState 效果很好,它是给定的:

pushd "%USERPROFILE%"
for /d /r %%h in (LocalState) do if exist "%%h" echo "%%h"
popd

但是当我尝试查找 Local State 文件夹时,使用几乎相同的行,它没有按预期显示路径,因为它在搜索到的文件夹周围添加了额外的引号。看到这个:

pushd "%USERPROFILE%"
for /d /r %%h in ("Local State") do if exist "%%h" echo "%%h"
popd

给出了这个,这很奇怪,因为无法在这个额外引用的路径上执行任何操作:

....
....
"C:\Users\<Username>\AppData\Local\BraveSoftware\Brave-Browser\User Data\"Local State""
"C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\"Local State""
....
....

现在我想知道是否只用一行我就可以使用批处理脚本在指定的文件夹中搜索 LocalStateLocal State 之类的文件夹名称?是这样的吗?

for /d /r %%h in ("Local? State") do if exist "%%h" echo "%%h"

它会以正确的引用格式显示路径,例如:?

....
    ....
    "C:\Users\<Username>\AppData\Local\BraveSoftware\Brave-Browser\User Data\Local State"
    "C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\Local State"
    ....
    ....

或者,如果这根本不可能,那么我如何才能找到带空格的文件夹名称并以正确的引用格式回显这些路径,而没有额外的、不需要的引号?

这将在 windowscmd batch-file 运行 下工作。

FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
    "(Get-ChildItem -Recurse -Directory -Filter 'Local*State').FullName"') DO (ECHO Directory name is %%~A)

需要 PowerShell 5.1 或更高版本。使用命令查找您的版本 $PSVersionTable.PSVersion.ToString()(Get-Host).Version.ToString()

为什么 FOR 命令行没有按预期工作?

字符串 LocalState"Local State" 不被 for 解释为要搜索的文件夹名称,因为它们都不包含 * 也不 ?。命令 FOR 仅搜索 non-hidden 文件或使用选项 /D 在指定通配符模式时搜索 non-hidden 文件夹。

尝试过:

for /d /r %%h in (LocalState) do if exist "%%h" echo "%%h"
for /d /r %%h in ("Local State") do if exist "%%h" echo "%%h"

上面的命令行导致递归搜索目录(包括隐藏目录)并分配给循环变量 h 每个找到的目录的完整路径未包含在 " 中连接 与指定的 字符串 LocalState"Local State".

示例:当前目录是C:\Temp,目录结构如下:

  • C:\温度
    • 开发与测试(!)
    • 文件夹 2

IF 条件执行时将以下字符串分配给循环变量 h:

  1. C:\Temp\LocalState
  2. C:\Temp\Development & Test(!)\LocalState
  3. C:\Temp\Folder 2\LocalState
  4. C:\Temp\"Local State"
  5. C:\Temp\Development & Test(!)\"Local State"
  6. C:\Temp\Folder 2\"Local State"

目录名称 4 到 6 有问题,因为它们本身包含两个双引号,导致执行 IF 条件时文件系统条目的指定名称不正确——目录或文件或重新分析点——在这种情况下,IF 没有任何区别,末尾没有反斜杠。

有人可能认为 FOR 的这种行为没有意义,但这种行为在某些用例中很有用,例如在每个用例中创建具有特定名称的文件目录树的文件夹。

这里的问题是不能在开头或结尾添加*,即使用*LocalState"Local State*",因为这会导致误报。 FOR 现在会真正搜索名称以 LocalState 结尾或以 Local State.

开头的 non-hidden 目录

所以使用下面的命令行是好的:

for /d /r %%h in (*LocalState "Local State*") do echo "%%h"

有哪些可能的解决方案?

一个非常快速的可能解决方案是:

for /F "delims=" %%h in ('dir "%USERPROFILE%\LocalState" "%USERPROFILE%\Local State" /AD /B /S 2^>nul') do echo "%%h"

在后台又启动了一个 cmd.exe,选项 /c' 中的指定命令行附加为附加参数。

DIR 首先搜索

  • 由于选项 /AD
  • 仅用于目录
  • 姓名LocalState或姓名Local State
  • 在指定目录下%USERPROFILE%
  • 它的所有子目录,因为选项 /S
  • 由于选项 /B(纯格式)和 /S.
  • ,仅输出完全限定的目录名称

DIR 非常聪明,可以在每个目录中搜索两个目录名称。因此,DIR 只针对两个目录名称同时搜索整个目录树一次。

一旦 DIR 完成,启动的 cmd.exe 将自行关闭。

处理批处理文件的 cmd.exe 实例捕获 DIR 输出的所有完全限定的文件夹名称,现在 FOR 处理它们一行一行。

FOR 选项 delims= 定义了一个空的分隔符列表,以关闭正常 space 和水平制表符上的默认行拆分行为。这是必需的,因为每个文件夹名称都应该一个接一个地完整分配给循环变量 h 以进行进一步处理,而不仅仅是完整文件夹名称中第一个 space 字符的部分。

其他解决方案是:

for /F "delims=" %%h in ('dir "%USERPROFILE%\Local*State" /AD /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /E /I /L /C:LocalState /C:"Local State"') do echo "%%h"
for /F "delims=" %%h in ('dir "%USERPROFILE%\Local*State" /AD /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /E /I /R /C:"Local *State"') do echo "%%h"

DIR 在这两种情况下搜索名称以 Local 开头并以 State (case-insensitive) 递归指定的目录文件夹 %USERPROFILE%.

在第一个命令行中使用了 FINDSTR 来过滤掉所有误报找到的目录,这些目录的完全限定目录名不以 case-insensitive 和字面意思结尾解释字符串 LocalState Local StateLocal & State.

在第二个命令行上使用了 FINDSTR 来过滤掉所有误报发现的目录,这些目录的完全限定目录名在末尾与 case-insensitive 不匹配解释的正则表达式 Local *State 匹配 LocalStateLocal State 以及 Local State(两个 space),因为 * 在此处被解释为 前导字符 (space) 零次或多次。请注意区别。在通配符模式中 * 表示 any 字符零次或多次,但在 FINDSTR 解释的正则表达式搜索字符串中不是这里这意味着 前面 个字符零次或多次。

DIR搜索带通配符的目录和用FINDSTR过滤掉误报的两种方案ectories 比仅使用 DIR 和要搜索的两个目录名称的解决方案要慢一些。

在所有提供的解决方案中,可以将 DIR 选项 /AD 修改为 /AD-L 以忽略连接点和符号目录链接(重新分析点)并仅查找真实目录。

为了了解使用的命令及其工作原理,请打开 command prompt window,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • dir /?
  • echo /?
  • findstr /?
  • for /?

阅读有关 Using command redirection operators 的 Microsoft 文档,了解 2>nul| 的解释。重定向运算符 >| 必须在 FOR 命令行上使用脱字符 ^ 进行转义,以便在 [=242] 时被解释为文字字符=] 命令解释器在执行命令 FOR 之前处理此命令行,该命令在后台启动的单独命令进程中执行嵌入式命令行。