FINDSTR和跳过文件夹

9

我是Windows批处理编程和Stack Overflow的新手,如果我问任何对您这些经验丰富、有才华的人来说显而易见的问题,请原谅。我正在使用Windows批处理(.bat)通过findstr查找包含特定字符串的文件。然而,我想跳过目录中的某些文件夹。

setlocal EnableDelayedExpansion
set basedir=C:\folder

for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
    findstr /i /m /s /c:"request" %basedir%\%%g *.* > %basedir%\Projects\list.txt
)

当我查看findstr输出的文件list.txt时,发现它搜索了我告诉它不要搜索的文件夹。也就是说,输出结果如下:

C:\folder\somefile.rtf
C:\folder\Requests\anotherfile.rtf
C:\folder\Projects\dontsearchme.txt
C:\folder\Archive\dontsearchmeeither.txt
C:\folder\Archive\Projects\dontsearchme.txt

如果它正常工作,只有C:\folder\somefile.rtfC:\folder\Requests\anotherfile.rtf将被包含在list.txt中。为了测试循环代码,我使用了以下内容:
setlocal EnableDelayedExpansion
set basedir=C:\folder

for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
    echo %basedir%\%%g
)

那段代码按预期工作,跳过了Projects和Archive文件夹。我猜问题与我的findstr调用方式有关,但我还没有找到错误。非常感谢任何见解!谢谢! -Alex

你尝试过将 findstr 命令中的 /s 参数去掉吗? - Matt Williamson
@MattWilliamson:我编辑了问题,以显示我确实想要搜索的子文件夹。当我删除“/s”时,“findstr”无法进入这些所需的文件夹。 - Alex A.
好的。我会将其从 Findstr 中移除,然后添加到 DIR 中,看看是否可以解决问题。 - Matt Williamson
4个回答

8

FINDSTR /S选项会搜索所有文件夹,从而绕过了您的FOR循环的意图。

Stephan成功地诊断出您代码的另一个问题,即重定向时使用覆盖模式而不是追加模式。

但是有一种更简单的方法可以获得您想要的结果。只需让FINDSTR搜索所有文件夹,并将结果传递到另一个FINDSTR中,以删除包含不需要的文件夹的结果。由于没有循环,您可以安全地使用覆盖模式进行重定向。

findstr /misl request "%basedir%\*" | findstr /liv "\\projects\\ \\archive\\" >"%basedir%\Projects\list.txt"

编辑

以上简单解决方案会浪费时间搜索后来被排除的文件夹。如果这些文件夹很大,这可能会浪费宝贵的时间。

以下脚本将不会扫描“%basedir%\Projects”或“%basedir%\Archive”文件夹。

@echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder

>"%basedir%\Projects\list.txt" (
  findstr /mil request "%basedir%\*"
  for /f "eol=: delims=" %%F in (
    'dir /a:d-h /b %basedir% ^| findstr /vixl "projects archive"'
  ) do findstr /smil request "%basedir%\%%F\*"
)

如果您想跳过所有树中命名为“Projects”或“Archive”的文件夹,则可以这样做:

@echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder

>"%basedir%\Projects\list.txt" (
  findstr /mil request "%basedir%\*"
  for /f "eol=: delims=" %%F in (
    'dir /s /a:d-h /b %basedir% ^| findstr /vir "[\\]projects[\\] [\\]archive[\\] [\\]projects$ [\\]archive$"'
  ) do findstr /mil request "%%F\*"
)

1
我喜欢它的简洁性。但是,这样做会查找所有包含“request”的文件,甚至在不需要的文件夹中,然后过滤这些结果,而不仅仅是搜索所需的文件夹吗?这很重要,因为我将在一个庞大的目录上运行它。非常感谢! - Alex A.
@Alex - 是的,扫描被排除的文件夹会浪费时间。请查看我的更新答案,其中包含一个可以完全绕过被排除文件夹的脚本。 - dbenham
当我运行它时,它仍然进入了我不想搜索的文件夹。 - Alex A.
@Alex - 是的,我忘记在第一个更新的答案中循环的FINDSTR上移除/S选项了。现在都已经修复好了。 - dbenham
现在它可以正常工作并且速度相当快,但是它现在省略了一些代码@Aacini发布的文件。导致这种情况的方法差异是什么? - Alex A.
@Alex - 其实,我第一次就做对了。/S选项需要在循环内部,并且应该过滤掉Projects和Archive文件夹。上一个解决方案是错误的,我需要使用正则表达式过滤器。现在两个都应该可以工作。 - dbenham

6
我遇到了类似的问题:我需要使用findstr来搜索所有.js文件,但不包括node_modules文件夹中的那些(即,我想搜索我的代码,但不是任何导入模块的代码)。这是我使用的命令: dir /S /B *.js | findstr /v /i node_modules | findstr /i /F:/ todo 命令的解释如下:
- dir /S /B *.js会输出当前目录和所有子目录中所有.js文件的完整路径。 - findstr /v /i node_modules对路径列表进行过滤,并删除包含字符串"node_modules"的任何路径。(/v标志使findstr输出不匹配的行。) - findstr /i /F:/ todo- "/F:/"告诉findstr从控制台接受要搜索的文件路径列表。
因此,只有通过“node_modules”筛选器的文件才会被搜索。

1
伟大的解决方案,精彩的描述。 - Seth
我们如何排除多个文件夹? - Sanora

1
你的问题是:使用重定向符号>时,每次都会覆盖你的list.txt文件;最后一次覆盖为空字符串。 请改用>>(追加到文件)替代。你的其余代码对我来说都能正常工作。

当我使用>>代替>时,什么也没有被写入到list.txt中。使用>输出到list.txt的结果符合预期。 - Alex A.
你已经发现了代码中的问题,但它与OP所述的问题无关。由于FINDSTR /S选项,代码的其余部分无法正常工作。 - dbenham

0

你的代码有几个难以理解的地方。你想要跳过文件夹,但是for /f %%g in ('dir /a:-h /b %basedir% 命令获取了所有非隐藏名称,包括文件和文件夹。最后你使用>来存储结果,所以只有最后一个findstr ... %%g的输出被存储在那个文件中。你必须像Stephan建议的那样使用>>。然而,我仍然不明白你是如何得到那个结果的!

我建议你修改你的代码,使其更简单,这样就可以更容易地理解和检测可能的错误。例如:

setlocal EnableDelayedExpansion
set basedir=C:\folder
set omitfolders=\Projects\Archive\
cd %basedir%
for /D %%g in (*) do (
   if "!omitfolders:\%%g\=!" equ "%omitfolders%" (
       findstr /i /m /s /c:"request" %basedir%\%%g\*.* >> %basedir%\Projects\list.txt
   )
)

if "!omitfolders:\%%g\=!" equ "%omitfolders%" 命令测试文件夹名称是否不在 omitfolders 变量中。


我想在 %basedir% 中搜索文件以及子文件夹中的文件。如果在循环追加到文件之前包含 findstr /imc:"request" %basedir%\*.* > %basedir%\Projects\list.txt,它就可以工作了。非常感谢您的帮助! - Alex A.

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