FINDSTR и пропуск папок

Я новичок в пакетном программировании для 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
)

Когда я смотрю в list.txt, файл, выведенный из findstr, я обнаруживаю, что папки, которые я запретил искать, были найдены. То есть вывод выглядит так:

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

Если бы он работал правильно, в list.txt были бы включены только C:\folder\somefile.rtf и C:\folder\Requests\anotherfile.rtf. Чтобы протестировать циклический код, я использовал следующее:

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
)

Этот код работает по желанию; он пропускает папки «Проекты» и «Архив». Я предполагаю, что проблема как-то связана с тем, как я звоню findstr, но я не смог определить ошибку моего пути. Любое понимание будет высоко оценено!

Большое спасибо!
-Алекс


person Alex A.    schedule 19.11.2013    source источник
comment
Вы пытались удалить /s из вашего findstr?   -  person Matt Williamson    schedule 19.11.2013
comment
@MattWilliamson: я отредактировал вопрос, чтобы показать, что есть подпапки, в которых я делаю поиск. Когда я удаляю /s, findstr не попадает в нужные папки.   -  person Alex A.    schedule 19.11.2013
comment
Ok. Я бы взял его из Findstr, но добавил в DIR и посмотрел, получится ли.   -  person Matt Williamson    schedule 19.11.2013


Ответы (4)


Параметр FINDSTR /S заставляет его искать все папки, тем самым обходя цель вашего цикла FOR.

Стефан успешно диагностировал еще одну проблему с вашим кодом, касающуюся перенаправления с использованием перезаписи вместо режима добавления.

Но есть гораздо более простой способ получить желаемый результат. Просто позвольте FINDSTR выполнить поиск во всех папках и передайте результат дополнительному FINDSTR, чтобы удалить результаты, содержащие ненужные папки. Поскольку цикла нет, вы можете безопасно использовать режим owverwrite для перенаправления.

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\*"
)

Если вы хотите пропустить все папки с именами «Проекты» или «Архив», независимо от того, где они находятся в дереве, то:

@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\*"
)
person dbenham    schedule 19.11.2013
comment
Я люблю простоту. Однако не будет ли это находить все файлы, содержащие запрос, даже в нежелательных папках, а затем фильтровать эти результаты, а не искать только нужные папки? Это важно, потому что я собираюсь запустить это в огромном каталоге. Спасибо большое! - person Alex A.; 19.11.2013
comment
@Alex - Да, сканирование исключенных папок будет пустой тратой времени. См. мой обновленный ответ для сценария, который полностью обходит исключенные папки. - person dbenham; 20.11.2013
comment
Когда я запускаю это, он все равно попадает в папки, которые я не хочу искать. - person Alex A.; 20.11.2013
comment
@Alex - Да, я забыл удалить параметр /S в зацикленном FINDSTR в первом обновленном ответе. Теперь все исправлено. - person dbenham; 20.11.2013
comment
Теперь он работает, и работает довольно быстро, но теперь пропускает некоторые файлы, которые код, опубликованный @Aacini, улавливает. В чем разница в подходе, которая может вызвать это? - person Alex A.; 20.11.2013
comment
@Alex - На самом деле, у меня все получилось с первого раза. Параметр /S должен присутствовать в цикле, и он должен отфильтровывать папки Projects и Archive. Последнее решение было неправильным, мне нужно было использовать фильтр регулярных выражений. Оба теперь должны работать. - person dbenham; 20.11.2013

У меня была аналогичная проблема: мне нужно было использовать 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».

person Derek Kurth    schedule 20.06.2016
comment
Отличное решение, отличное описание. - person Seth; 29.12.2016
comment
Как бы мы исключили несколько папок? - person Sanora; 31.07.2021

ваша проблема: при перенаправлении > вы каждый раз перезаписываете свой list.txt; последний раз, когда вы перезаписываете его пустой строкой. Вместо этого используйте >> (добавить в файл). Остальная часть вашего кода работает для меня.

person Stephan    schedule 19.11.2013
comment
Когда я использую >> вместо >, в list.txt ничего не записывается. Вывод в list.txt работал, как и ожидалось, с использованием >. - person Alex A.; 19.11.2013
comment
Вы выявили проблему с кодом, но она не имеет ничего общего с заявленным вопросом ОП. Остальной код работает неправильно из-за параметра FINDSTR /S. - person dbenham; 19.11.2013

В вашем коде есть пара моментов, которым трудно следовать. Вы хотите пропустить папки, но команда for /f %%g in ('dir /a:-h /b %basedir% получает все нескрытые имена, включая файлы и папки. В конце вы используете > для сохранения результатов, поэтому в этом файле сохраняется только вывод последнего findstr ... %%g. Вместо этого вы должны использовать >>, как указывает Стефан. Однако я до сих пор не понимаю, как вы получаете такой результат!

Я предлагаю вам изменить свой код, чтобы сделать его проще, чтобы его было легче отслеживать и обнаруживать возможные ошибки. Например:

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.

person Aacini    schedule 19.11.2013
comment
Я хочу искать файлы в %basedir%, а также файлы во вложенных папках. Это работает, если я включу findstr /imc:"request" %basedir%\*.* > %basedir%\Projects\list.txt перед циклом, который добавляется к файлу. Большое спасибо за помощь! - person Alex A.; 19.11.2013