首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使findstr过滤“上次修改”文件?

如何使findstr过滤“上次修改”文件?
EN

Stack Overflow用户
提问于 2015-11-13 14:17:43
回答 3查看 1.3K关注 0票数 0

我希望捕获一组存储在文件夹和所有子文件夹中的文件的项目版本。

使用:

代码语言:javascript
复制
@echo off<br>
findstr /s "ProjectVersion" C:\srm2\reg\*.cpf > C:\RESULTS.txt

返回文件夹中的每个.cpf文件。

例如:

C:\srm2\reg \132L\reg\132L\reg\13804.C:C:C:\srm2\reg\132L\reg\132L 18122014121012.cpf:C:C:\srm2\reg\reg132L\reg\reg132L\reg2014121731.cpf:C:\srm2\dann-20151112-134545.cpf:C:\srm2\reg丹尼-20151113-0835cpf:C:C:\srm2\reg\reg\rg丹尼-20151113-08566cpf:C:srm2\reg\rg丹尼-20151113-08565ppf:C:丹尼-20151113-102018.cpf: C:\srm2\reg\DANNY\DANNY.cpf:

如何筛选以仅返回每个子文件夹.cpf中的上一次修改的文件,因为有些文件夹有多个相同文件的版本?

EN

回答 3

Stack Overflow用户

发布于 2015-11-13 17:02:52

我在this post上复制了答案,它表明:“您可以批量编写递归算法,使您能够精确地控制在每个嵌套子目录中所做的操作”,并对其进行了稍微的修改,以解决这个问题。这种方法与其他答案是一样的:遍历树,在每个子文件夹中执行findstr,只使用最后修改日期所命令的第一个文件;不同的是,这个过程是通过代码显式实现的,而不是通过for /Rdir /S命令实现的。

代码语言:javascript
复制
@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
票数 1
EN

Stack Overflow用户

发布于 2015-11-13 14:51:48

代码语言:javascript
复制
@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
EN

Stack Overflow用户

发布于 2015-11-13 15:00:49

您可以使用for /R /D递归遍历所有目录,然后使用dir /B /A:-D /O:-D返回按日期排序的文件列表(首先是最新的),并通过for /F解析其输出,只接受第一项,因此您只能枚举每个目录中的一个最新文件:

代码语言:javascript
复制
@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 (将接收当前迭代目录中的最新文件),
  • 变量名LINE (将接收与搜索字符串匹配的文件中的行),
  • 添加了文件模式reg*.cpf的当前迭代目录,以及
  • 所需的搜索字符串ProjectVersion

最后,将检查变量LINE是否为空,如果不是,则由echo输出包含文件路径、冒号和查找行的行。

注意,所有输出都重定向到文件C:\results.txt中。

之所以选择这种使用子例程的方法,是因为有一个goto命令用于在第一次迭代时终止一个特定的for循环(请参阅上面的描述),但不是全部。goto实际上破坏了放置在其中的所有块上下文,甚至所有嵌套上下文。for循环只是一种块命令,比如if子句,或者简单的分组命令()。使用子例程可以防止放置在子例程中的goto破坏主例程的块。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33694797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档