【问题标题】:Search Directory for Files Matching Pattern - Windows文件匹配模式的搜索目录 - Windows
【发布时间】:2020-08-03 15:12:44
【问题描述】:

我一直试图让这项工作比我愿意承认的时间更长,但由于某种原因我无法弄清楚。我通常使用 Linux/Unix。

我只想在目录中搜索文件名与字符串匹配的所有实例。

我尝试过的一些事情:

dir /s "/path/to/Test*"

dir /s/b "C:/path/to/Test*"

此外,我希望返回可以轻松导入数组的内容。没有不必要信息的东西。我只需要匹配的每个文件的路径或至少文件名。

编辑:我不想要这样的信息(如果可能的话)

 Volume in drive C is OS
 Volume Serial Number is...

编辑:Test* 旨在表示所有以Test 开头的文件名。所以TestATestBTestC应该都匹配。

【问题讨论】:

  • 对文件路径使用正斜杠对于 CMD 的内部命令以及许多外部命令都是不可靠的。我没有详细的列表,说明哪些命令在某些(不是全部)情况下使用正斜杠,哪些总是需要反斜杠。当我不小心使用了错误的分隔符时,我被随机绊倒了很多次。始终使用反斜杠作为 CMD 中的路径分隔符。 OTOH,PowerShell 命令应始终支持使用正斜杠作为路径分隔符。

标签: windows cmd


【解决方案1】:

相同的命令适用于 Linux、Mac 和 Windows。 http://github.com/PowerShell/PowerShell/

PS C:\src> (Get-ChildItem -Recurse -File -Path 'C:/src/d2' -Filter 'test*').FullName
C:\src\d2\test.bat
C:\src\d2\test.ps1
C:\src\d2\test.sql
C:\src\d2\test.txt
C:\src\d2\copyt\test.txt

使用命令别名,可以缩短交互使用的时间。但是,别名不是脚本的好习惯。

PS C:\src> (ls -r -file 'C:/src/d2/test*').FullName
C:\src\d2\test.bat
C:\src\d2\test.ps1
C:\src\d2\test.sql
C:\src\d2\test.txt
C:\src\d2\copyt\test.txt

如果你想要一个数组,这将是一个。

PS C:\src> $files = (ls -r -file 'C:/src/d2/test*').FullName
PS C:\src> $files.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

用 -replace 替换目录分隔符。

(Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/'

使用 -join 将它们连接到一行。此连接使用逗号。请注意,如果连接使用 *NIX 样式的冒号,它在 Windows 上将无法正常工作。

PS C:\src> (Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/' -join (',')
C:/src/d2/test.bat,C:/src/d2/test.ps1,C:/src/d2/test.sql,C:/src/d2/test.txt,C:/src/d2/copyt/test.txt

如果您需要 PATH 样式的分隔符,请使用:

(Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/' -join ([IO.Path]::PathSeparator)

【讨论】:

  • 尝试后,它似乎可以按我的需要工作。关于此解决方案的另外两个问题。首先有没有办法(没有太多额外的开销)用正斜杠返回文件名?其次,id 喜欢在响应中添加分隔符。怎么可能做到这一点?第一个问题远不如第二个重要
  • @Newb4YouBB,您是在寻找单行的 CSV 或 PATH 样式列表吗?
  • 所以让我解释一下我的情况。我需要一个匹配模式的文件名数组,以便在 PHP 中使用。传统上(使用 Linux)我会使用 find 来执行此操作,但是因为我在本地对此进行测试,所以我需要一个(接近)等效的 Windows 解决方案。因为这只是为了测试它不需要是一个完美的解决方案。我只是希望将数组或其他内容轻松更改为数组,以便脚本的其余部分可以保持不变。
  • 感谢您的额外帮助。 replace 运算符似乎不想为我工作,但我可以从这里拿走它。
【解决方案2】:

抱歉,我没有看到您习惯使用 UNIX/Linux,所以这里我有一个您更喜欢的方法:

forfiles /P C:\ /S /M test* /C "cmd /c echo @path"

执行以下操作:

/P C:\              Start looking in C:\
/S                  Search through subdirectories
/M test*            Filename looks like "test*"
/C <cmd>            When found, launch <cmd>
"cmd /c echo @path" Echo (write to output) the complete path of the found file or directory

这会给你一个文件和目录的列表,写成完整的路径,比如:

"C:\Octave\Octave-5.2.0\mingw64\bin\test-libiberty.exe"
"C:\Octave\Octave-5.2.0\mingw64\bin\test-lua.exe"
"C:\Octave\Octave-5.2.0\mingw64\bin\test-tinyxml.exe"
"C:\Octave\Octave-5.2.0\mingw64\include\llvm\Testing"         <-- this is a directory
"C:\Octave\Octave-5.2.0\mingw64\include\wx-3.0\wx\testing.h"
...

这与您习惯的典型 UNIX/Linux 结果非常相似。

有关forfiles 的更多信息,请参阅启动forfiles /?

【讨论】:

    【解决方案3】:

    我刚刚使用这个简单的命令在我的 C:-drive 中搜索所有名为“test.*”的文件:

    dir /S C:\test*
    

    虽然我只提到了目录C:\/S 确保所有子文件夹也都被使用。最重要的是,如您所见,没有双引号。

    这能解决您的问题吗?

    【讨论】:

    • 因此,当我在不带引号的情况下执行此操作时,它会告诉我其中一个目录名称的格式不正确。当我添加引号时,它会通知我当我确实知道文件存在并且位于正确的位置时找不到该文件。
    【解决方案4】:

    根据您的陈述,“我希望返回可以轻松导入数组的东西”,我假设您可能正在寻找更像这样的东西:

    @Echo Off
    Rem Ensure that extensions are enabled (required for SET and FOR commands)
    SetLocal EnableExtensions
    Rem Ensures that there are no existing variables in the environment with names beginning with file[
    For /F "Delims==" %%G In ('" Set file[ 2> NUL "') Do Set "%%G="
    Rem Gets every file matching the glob test* in the tree rooted at "C:\path\to"
    Rem and defines an incremented variable name for each, beginning at %file[1]%
    For /F "Tokens=1,* Delims=]" %%G In (
        '" Dir /B /S /A-D "C:\path\to\test*" 2> NUL | "%__AppDir__%find.exe" /N /V "" "'
    ) Do Set "file%%G]=%%H"
    Rem An example line to show you all of the variables you have now defined
    Set file[ 2> NUL
    Rem Pause the script to ensure that you have been able to read any output
    Pause
    Rem An example line to show you all the first defined variable value
    Echo=%file[1]%
    Rem Pause the script to ensure that you have been able to read any output
    Pause
    

    ...这里没有Remarks:

    @Echo Off
    SetLocal EnableExtensions
    For /F "Delims==" %%G In ('" Set file[ 2> NUL "') Do Set "%%G="
    For /F "Tokens=1,* Delims=]" %%G In (
        '" Dir /B /S /A-D "C:\path\to\test*" 2> NUL | "%__AppDir__%find.exe" /N /V "" "'
    ) Do Set "file%%G]=%%H"
    Set file[ 2> NUL
    Pause
    Echo=%file[1]%
    Pause
    

    不要忘记根据您的特定位置和全局的需要更改 C:\path\to\test*

    【讨论】:

    • 我还没有尝试过这个解决方案。我打算将它与 PHP 的 shell_exec() 一起使用,所以我认为这需要写入文件然后执行?另外,请原谅我的无知,但这似乎很冗长。 Windows 中是否没有任何内容可以更直接地完成我需要的内容?
    • 我已经回答了你问@Newb4YouBB 的问题,我不会回答你没有问的问题,或者调整这个以适应事后改变的问题。此外,如果您没有尝试过,那么在发布上述评论六分钟后接受另一个答案是不公平的,(即使我愿意,我也无法修改我的答案,或者您可以确定哪种解决方案对于您提供的标签下提出的特定问题对您更有用)。
    • 另外,我相当肯定,如果另一个答案被证明“更”正确,您可以更改已接受的答案。
    • 你可以@Newb4YouBB,唯一的问题是在你全部尝试之前太急于选择一个,这会让其他响应者失去动力,并可能阻止其他答案,(因为很多会员不喜欢争夺无价值的积分).
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多