FINDSTR - 添加 "date modified" 个文件作为每个结果的前缀

FINDSTR - add "date modified" of the files as a prefix to each result

我正在寻找一些命令添加到我的脚本中。 该脚本遍历文本日志文件的文件夹并查找作为输入传递的字符串。
不幸的是,日志文件以设定的大小溢出并且文件名中没有日期,只有数字后缀和字符串前缀。在日志文件行中只有事件发生的时间,没有日期。日期在 12 点钟位置添加为单行。

完成搜索的文件夹示例:

Logfile_001.txt
Logfile_002.txt
Reboot-01_Logfile_001.txt
Reboot-01_Logfile_002.txt
Reboot-01_Logfile_003.txt
Reboot-02_Logfile_001.txt
Reboot-02_Logfile_002.txt

我想在FINDSTR结果的每一行中添加搜索文件的"date modified"属性

我当前的代码:

@ECHO off
DEL /F _Result.searchresult
SET /P searchterm=Enter search term: 
@ECHO Searching for %searchterm% >_Result.searchresult
@ECHO --------------------------------------------- >>_Result.searchresult
FINDSTR /S /C:"%searchterm%" *.txt >>_Result.searchresult
_Result.searchresult

当前结果:

Reboot-79_Logfile_001.txt:08:29:05.586 loginfo
Reboot-79_Logfile_001.txt:08:30:05.586 loginfo

想要的结果:

2019/08/13 Reboot-79_Logfile_001.txt:08:29:05.586 loginfo
2019/08/13 Reboot-79_Logfile_001.txt:08:30:05.586 loginfo

或:

Reboot-79_Logfile_001.txt:2019/08/13 08:29:05.586 loginfo
Reboot-79_Logfile_001.txt:2019/08/13 08:30:05.586 loginfo

其中"2019/08/13"是文件Reboot-79_Logfile_001.txt

的"date modified"属性的日期

@OP 我不得不做一个小改动,因为我最初是在火车上 phone 上写的,我犯了几个错别字等,当你测试时出现了

特别是这两个单个字符的变化:

"Tokens=1* NOT "Token=1*

SET "_DateMatched=1" NOT SET "_DateMatched="

为此,使用循环从查找字符串的结果中分离出文件名,然后从中获取日期以用于回显。

脚本

@(
  SETLOCAL
  ECHO OFF
  SET "_ResultFile=_Result.searchresult"
  SET "_DateMatched="
)
DEL /F /Q "%_ResultFile%"
SET /P "_SearchTerm=Enter search term: "

ECHO Searching for %_SearchTerm% >"%_ResultFile%"
ECHO --------------------------------------------- >>"%_ResultFile%"

FOR /F "Tokens=1* delims=:"  %%A IN ('
  FINDSTR /S /C:"%_SearchTerm%" *.txt
')  DO (
  For %%a in ( %%~tA ) Do (
    IF NOT DEFINED _DateMatched (
      ECHO.%%a %%A:%%B>>"%_ResultFile%"
      SET "_DateMatched=1"
    )
  )
  SET "_DateMatched="
)

结果

Searching for ggg 
--------------------------------------------- 
 08/13/2019 test.txt:ggg
 08/13/2019 test2.txt:ggg

此外,是的,您可以使用 FOR /F 而不是 50/50 硬币翻转 II 确实使用用 FOR 循环而不是 FOR /F 循环定义的 defined/not。

然而,提供的其他答案选择了这条路径,但出于某种原因使用我的代码作为基础并添加到第三个循环中,因此它们的中间循环是多余的。

我将 post 此处的备选方案以及我曾考虑过的 post 两种方式,一种方式是六个,另一种方式是六个。 (但我不会在额外的循环上浪费你的时间,我仍在绞尽脑汁地添加它!)

替代版本

@(
  SETLOCAL
  ECHO OFF
  SET "_ResultFile=_Result.searchresult"
)
DEL /F /Q "%_ResultFile%"
SET /P "_SearchTerm=Enter search term: "

ECHO Searching for %_SearchTerm% >"%_ResultFile%"
ECHO --------------------------------------------- >>"%_ResultFile%"

FOR /F "Tokens=1* delims=:"  %%A IN ('
  FINDSTR /S /C:"%_SearchTerm%" *.txt
')  DO (
  For /F %%a in ("%%~tA") Do (
      ECHO.%%a %%A:%%B>>"%_ResultFile%"
  )
)

虽然每种方法之间确实没有功能差异,但我在犹豫第一种还是第二种更美观,所以这对我来说是先抛硬币还是先写还是两种都写.

那是说试图为我收到的一些奇怪的评论创造一个合理的理由,因为我在 post 对我的代码进行了一些本质上非功能性的小改动,但代码的核心仍然是我的东西写了,只是选择显示 FOR /F 方法,但是这样做会产生不必要的第三个循环。

我认为 FOR /F 有一些小好处,它节省了大约 50 个字符的代码,虽然在这种情况下它确实是 50/50,但在某些情况下我肯定会选择它作为下一步要快一点,尽管在这种情况下我们对一场比赛只有 3 次迭代,所以我怀疑在当前情况下我们需要有成千上万场比赛才能显着影响结果。

就是说,通过添加另一个评论中的第三个不需要的循环,我怀疑任何速度优势都被取消了,所以..我不确定,至少在我提供的上面的代码中没有不需要的循环,所以如果有速度效益音乐会,请尝试使用它。 :)

插入文件的时候,你需要另一个for来剥离它。

:: Q:\Test19\SO_57475301.cmd
@ECHO OFF
SET /P "_searchterm=Enter search term: "

(ECHO Searching for %_searchterm%
 ECHO ---------------------------------------------
 FOR /F "tokens=1* delims=:" %%A IN ('
  FINDSTR /C:"%_searchterm%" *.txt
 ')  DO For %%a in ("%%A") Do For /F %%D in ("%%~ta") do ECHO:%%D %%A:%%B
) >"_Result.searchresult"

示例输出:

> SO_57475301.cmd
Enter search term: log

> type _Result.searchresult
Searching for log
---------------------------------------------
08/13/2019 Reboot-79_Logfile_001.txt:08:29:05.586 loginfo
08/13/2019 Reboot-79_Logfile_001.txt:08:30:05.586 loginfo

要文件名先重新排序ECHO:%%A:%%D %%B

这是一种获得你想要的东西的方法。

=== grepplus.ps1

Get-ChildItem -File -Path 'C:/src/t' -Filter '*.ps1' |
    Select-String '^S' |
    ForEach-Object {
        '{0} {1}:{2}' -f (
             (((Get-ChildItem $_.Path).LastWriteTime).ToString('yyyy/MM/dd') -replace '-','/'),
             $_.Filename,
             $_.Line
        )
    }

=== grepplus.bat

@ECHO OFF
powershell -NoLogo -NoProfile -Command ^
    "Get-ChildItem -File -Path 'C:/src/t' -Filter '*.ps1' |" ^
        "Select-String '^S' |" ^
        "ForEach-Object {" ^
            "'{0} {1}:{2}' -f (" ^
                "(((Get-ChildItem $_.Path).LastWriteTime).ToString('yyyy/MM/dd') -replace '-','/')," ^
                "$_.Filename," ^
                "$_.Line" ^
            ")" ^
        "}"

这是我的 转换为答案,因为我希望它可能有用......

而不是简单的findstr /S command line you could try something with a for loop that iterates over the files. To get the file date/time stamps (last modification) and the pure file names you could make use of ~-modifiers like ~t and ~nx, respectively. To capture the output of findstr use a for /F loop;然后你就可以将它与其他字符串连接起来了。

这样的东西对你有用(我希望):

(
    for %%I in ("*.txt") do (
        for /F "delims=" %%S in ('findstr /C:"%searchterm%" "%%~I"') do (
            for /F %%T in ("%%~tI") do (
                echo %%T:%%~nxI:%%S
            )
        )
    )
) >> "_Result.searchresult"

第二个 for /F 循环试图从 %%~tI 部分返回的 date/time 值中分离出纯日期,但请注意该值是区域设置相关的!

上述方法不会递归子目录来查找匹配文件。尽管如果您真的想这样做,请将行 for %%I in ("*.txt") do ( 替换为 for /R %%I in ("*.txt") do (