2015-11-13 5 views
0

Я ищу, чтобы захватить версию проекта в наборе файлов, хранящихся в папке и во всех подпапках.Как получить findstr для фильтрации файлов «последнего изменения»?

Использование:

@echo off<br> 
findstr /s "ProjectVersion" C:\srm2\reg\*.cpf > C:\RESULTS.txt 

Возвращает каждый .cpf файлов в папках.

например.

C:\srm2\reg\132L\132L-20151111-150804.cpf: <ProjectVersion Major="8" Minor="0" Build="22" Revision="20312" /> 
C:\srm2\reg\132L\132L.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="20312" /> 
C:\srm2\reg\132L\132L18122014121012.cpf: <ProjectVersion Major="8" Minor="0" Build="22" Revision="20312" /> 
C:\srm2\reg\132L\132L18122014121731.cpf: <ProjectVersion Major="8" Minor="0" Build="22" Revision="20312" /> 
C:\srm2\reg\DANNY\DANNY-20151112-134545.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="0" /> 
C:\srm2\reg\DANNY\DANNY-20151113-083530.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="0" /> 
C:\srm2\reg\DANNY\DANNY-20151113-085621.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="0" /> 
C:\srm2\reg\DANNY\DANNY-20151113-102018.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="0" /> 
C:\srm2\reg\DANNY\DANNY.cpf: <ProjectVersion Major="11" Minor="0" Build="0" Revision="0" /> 

Как я могу фильтровать, чтобы вернуться только Последнее изменение .cpf файла в каждой подпапке, так как некоторые папки имеют множество версий одного и того же файла?

+0

Пожалуйста, сообщите нам, что вы пробовали до сих пор, редактируя сообщение! – aschipfl

ответ

0
@ECHO OFF 
SETLOCAL ENABLEDELAYEDEXPANSION 
SET "sourcedir=U:\sourcedir" 
SET "lastdir=" 
FOR /f "delims=" %%a IN ('DIR /s /b /a-d /o-d "%sourcedir%\*.bat" ') DO IF "!lastdir!" neq "%%~dpa" (
FINDSTR /i "z" "%%a" >NUL 
IF NOT ERRORLEVEL 1 (
    ECHO(%%a 
    SET "lastdir=%%~dpa" 
) 
) 

GOTO :EOF 

Вы должны были бы изменить установку sourcedir в соответствии с вашими обстоятельствами.

Одна строка кода, которую вы предоставляете, не работает вообще.

Эта процедура просто создает каталог из *.bat файлов в базовой форме (только для полного файла), но отсортирован в порядке обратного дат и исключает имена каталогов.

Отчет находится в обратном/временном порядке в каждом каталоге, поэтому первое совпадающее имя файла для любого каталога - это последний файл.

Если имя каталога было изменено, затем выполните команду findstr, чтобы найти требуемое ключевое слово. Если он найден, errorlevel установлен в 0, следовательно, это не 1 or greater, поэтому имя файла отображается в эхом, а lastdir - в имени файла файла.

Я просто использовал *.bat файлы и искал "z" witin эти файлы для тестирования. При необходимости отрегулируйте.

0

Вы можете использовать for /R /D рекурсивно пройти через все каталоги, а затем использовать dir /B /A:-D /O:-D возвращать список файлов, отсортированных по дате (сначала новые) и разобрать его выход на for /F принимать только первый элемент, поэтому перечислим только один новейший файл в каждом каталоге:

@echo off 
setlocal EnableExtensions EnableDelayedExpansion 
> "C:\results.txt" (
    for /D /R %%D in ("C:\srm2\reg\*.*") do (
     call :SUB FILE LINE "%%~fD\*.cpf" "ProjectVersion" 
     if defined LINE (
      echo/!FILE!:!LINE! 
     ) 
    ) 
) 
endlocal 
exit /B 

:SUB var_file var_line pattern string 
set "%~1=" & set "%~2=" 
for /F "eol=| delims=" %%F in ('dir /B /A:-D /O:-D "%~3"') do (
    set "%~1=%%~fF" 
    for /F "delims=" %%L in ('findstr /L "%~4" "%%~fF"') do (
     set "%~2=%%L" 
     goto :EOF 
    ) 
    goto :EOF 
) 

Давайте посмотрим на подпрограмму :SUB первый, который предназначен для выполнения один раз в каждом каталоге. Это требует 4 параметра:

  • (%~1) имя переменной провести путь к найденному файлу,
  • (%~2) имя переменной провести линию, соответствующую строку поиска,
  • (%~3) шаблон, чтобы получить отсортированный список файлов (сперва сначала) и
  • (%~4) строка поиска (ожидается, что она будет не более одного раза на файл).

Внешний for /F цикл разбирает вывод команды dir /B /A:-D /O:-D "%~3", который фактически строит упорядоченный список файлов. Цикл требует итерации по каждой отдельной строке, но поскольку в конце есть goto :EOF, цикл прерывается после первой итерации, поэтому обрабатывается только первый (и, следовательно, самый новый) элемент списка. Путь к этому элементу присваивается первой переменной, заданной в качестве аргумента. Если элементы не соответствуют шаблону файла, переменная остается пустой.

Внутренняя петля for /F анализирует выход команды поиска findstr. Так как ожидается только одно вхождение поисковой строки, этот цикл должен повторяться только один раз. Если совпадение найдено, содержащая строка присваивается второй переменной, заданной в качестве аргумента. Если совпадение не найдено, переменная остается пустой.

Теперь давайте рассмотрим основную рутину. Это рекурсивно проходит через дерево каталогов, используя for /D /R и выполняет итерацию по всем каталогам. Для каждого из них, подпрограмма :SUB называется, проходя через следующие аргументы:

  • имя переменной FILE (получит новейший файл в настоящее время itereted каталога),
  • имя переменной LINE (получит линию файл, который соответствует строке поиска),
  • в данный момент итерацию каталог с файлом шаблона reg*.cpf дописывается, и
  • требуемая строка поиска ProjectVersion.

Наконец, переменная LINE проверяется на пустоту, и если нет, то строка, содержащая путь к файлу, двоеточие и найденную строку выводится echo.

Обратите внимание, что все выходные данные перенаправляются в файл C:\results.txt.

Этот подход с использованием подпрограммы был выбран, поскольку существует команда goto, используемая для завершения одного определенного цикла for при его первой итерации (см. Описание выше), но не все из них. goto фактически разбивает все контексты блоков, в которые он помещается, даже все вложенные. for Петли - всего лишь своего рода команда блока, например, if, или просто сгруппированные команды (). Использование подпрограммы предотвращает разбиение блоков основной процедуры на goto, помещенных в подпрограмму.

+0

Я сделал небольшую доработку, так как я не видел обратную косую черту между 'reg' и' *.cpf', поэтому я рассматривал 'reg' как часть имени файла, а не каталога; однако функциональный код остается тем же ... – aschipfl

1

Я скопировал ответ на this post, которые указывают: «Вы можете написать рекурсивный алгоритм в Batch, который дает вам точный контроль того, что вы делаете в каждой вложенной поддиректории» и слегка модифицировал его для того, чтобы решить эту проблему , Подход такой же, как и другие ответы: пройдите по дереву и в каждой подпапке выполните findstr только с первым файлом, упорядоченным по последней измененной дате; разница в том, что этот процесс явно достигается посредством кода, а не через for /R или dir /S команд.

@echo off 
setlocal EnableDelayedExpansion 
cd C:\srm2\reg 
call :treeProcess > C:\RESULTS.txt 
goto :EOF 


:treeProcess 
set "output=" 
for /F "delims=" %%f in ('dir /B /A:-D /O:D *.cpf') do if not defined output (
    for /F "delims=" %%o in ('findstr "ProjectVersion" "%%f"') do set "output=!cd!\%%f: %%o" 
) 
if defined output echo !output! 

rem Recursive call 
for /D %%d in (*) do (
    cd %%d 
    call :treeProcess 
    cd .. 
) 

exit /b 
+0

Отличный подход, @Aacini, +1! как насчет выполнения таких рекурсивных вызовов? – aschipfl

+0

Работает на сервере, но выплевывает ECHO с большим количеством :) – Mick

+0

@Mick: Это происходит, когда в одной подпапке есть _not_ есть файл '* .cpf'! Просто добавьте 'if defined output' перед' echo! Output! 'В коде. Я уже сделал это в ответ ... – Aacini