批处理文件:从日志文件中读取最后一行并将其复制到新文件

时间:2015-01-14 15:50:32

标签: batch-file

这是我的第一个帖子,所以如果格式不符合预期,请原谅我。 (建议

欢迎改进。)

我正在尝试创建一个批处理文件,它将从日志文件读取最后一行并将它们复制到新文件中。

到目前为止,我发现here是一种阅读最后一行的方法。

代码如下:

for /f %%i in ('find /v /c "" ^< someFile.txt') do set /a lines=%%i
set /a startLine=%lines% - 1
more /e +%startLine% someFile.txt > lastLines.txt

以上代码一次只能处理一个文件。我需要的是从已知列表中的所有文件中读取最后一行,并将此行添加到新的.csv文件中。

我一直在使用以下代码获取日志文件中的第4个条目,但它返回每个日志文件的每一行:

for /f %%x in (%list%) do for /f "delims=.txt,  tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv

我需要的是两者的组合,但我不知道如何组合它们并将完整的最后一行复制到.csv文件。

=== @Magoo: 谢谢你的反应。 在每个日志文件中可以是1到> 100行,用逗号分隔的信息。类似的东西:

"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E" 

第4个条目的最后一个代码用于获取已登录到计算机的所有帐户的列表。这段代码给了我一个非常大的列表,列出了我在%list%中检查的所有计算机日志上的所有登录/注销事件。 在%list $中,我有我想要检查的所有日志文件的名称。这返回了所有行。

对于新的批处理文件,我只需要最后一次登录/注销,我想要整个最后一行。

所以我有一个.txt文件,其中包含我需要检查的所有计算机的主机名。 此.txt文件将通过变量%list%。

逐行读取

从每个日志文件中我只需要将最后一行复制到输出文件中。

=== 我刚试过JosefZ提供的解决方案。不幸的是,这对我来说还不行。没有最后一行被复制到结果文件中。在代码中我删除了可能的最后一行的额外条目,因为日志中没有空行,我还在结果中添加了一个我希望在主机名中可用的条目。 JosefZ在那里有文件名:

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion    
type nul>output.csv    
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
  set "host=%%~x" 
  for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
  call :lline
)    
:endlocal
@ENDLOCAL
goto :eof    
:lline    
  set "filename=.\logs\%filename:&=^&%.txt"
  echo %host%,%lastline%>>output.csv
goto :eof

结果文件仅显示主机名。我会对此感到困惑,但欢迎所有提示!

=== 明白了!!!

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion

type nul>output.csv

set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
  set filename=   :: *empty previous filename*
  set lastline=   :: *empty previous lastline* 
  set "host=%%~x" 
  set "filename=.\logs\%host%.txt"  :: *creating the filename from path+hostname+extention*
  for /F "tokens=*" %%G in ('type "%filename%"') do set "lastline=%%G"
  call :lline
)

:endlocal
@ENDLOCAL
goto :eof

:lline

  echo %host%,%lastline%>>output.csv

goto :eof

2 个答案:

答案 0 :(得分:1)

如果文件中有更多尾随空行,则使用行号的方法可能会失败。幸运的是for /F循环忽略(不迭代)空行;让我们使用这个功能:在下一个练习的脚本中使用:

  • disabledelayedexpansion允许文件名中的!
  • set "list=_listing.txt"其中_listing.txt包含文件名列表(包含完整路径和扩展名.txt),一行中有一个文件名:dir /b /s *.txt>_listing.txt
  • type nul>files\output.csv清空输出文件(可选)
  • set "lastline=!!!file empty!!!"初始化变量%lastline%;也可以是set "lastline="
  • call :lline处理变量%filename%%lastline%
  • set "filename=%filename:&=^&%"允许文件名中的&

脚本如下:

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion
type nul>files\output.csv

set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
  set "filename=%%~x"
  set "lastline=!!!file empty!!!"

  rem the whole line
  for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"

  rem the fourth token only
  rem for /F "tokens=4" %%G in ('type "%%~x"') do set "lastline=%%G"

  call :lline
)
:endlocal
@ENDLOCAL
goto :eof

:lline
  set "filename=%filename:&=^&%"
  echo %filename% %lastline%
  rem >>files\output.csv
goto :eof

示例_listing.txt文件:

d:\bat\files\1exclam!ation.txt
d:\bat\files\2exc!lam!ation.txt
d:\bat\files\11per%cent.txt
d:\bat\files\12per%cent%.txt
d:\bat\files\17per%Gcent.txt
d:\bat\files\18per%%Gcent.txt
d:\bat\files\21ampers&nd.txt
d:\bat\files\22ampers&&nd.txt

输出:

d:\bat>lastlines
d:\bat\files\1exclam!ation.txt 0 15.01.2015  1:52:28.48 -15072 20465
d:\bat\files\2exc!lam!ation.txt 6 15.01.2015  1:52:28.50 3250 16741
d:\bat\files\11per%cent.txt -8 15.01.2015  1:52:28.50 -3692 27910
d:\bat\files\12per%cent%.txt !!!file empty!!!
d:\bat\files\17per%Gcent.txt 0 15.01.2015  1:52:28.56 14508 12374
d:\bat\files\18per%%Gcent.txt 1 15.01.2015  1:52:28.56 30540 26959
d:\bat\files\21ampers&nd.txt 15.01.2015  1:22:50.18
d:\bat\files\22ampers&&nd.txt 15.01.2015  1:22:50.18

老实说,所有这些镇流器都是(可能)在文件中尾随空行,并且仅用于文件名中的!&;一切都可以用

完成
for /f %%x in (%list%) do for /f "skip=%startLine% tokens=4" %%i in (%%x) do echo %%x, %%i >> output.csv

答案 1 :(得分:1)

您应该使用简单的FOR来迭代值列表,而不是FOR / F.

以下内容应该有效:

@echo off
setlocal enableDelayedExpansion
>>output.csv (
  for %%F in (
    "file1.log"
    "file2.log"
    "file3.log"
    etc.
  ) do (
    for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
    more +!skip! %%F
  )
)

如果您获得带空格的名称,那么文件名周围会有引号。

如果它看起来像你可以使用你的LIST变量
set LIST="file1.log" "file2.log" "file3.log" etc.

@echo off
setlocal enableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.    
>>output.csv (
  for %%F in (%LIST%) do (
    for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
    more +!skip! %%F
  )
)

如果您的任何文件名包含!字符,则必须在循环内切换延迟扩展ON和OFF。否则,延迟扩展将在%%F扩展时损坏名称。

@echo off
setlocal disableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.    
>>output.csv (
  for %%F in (%LIST%) do (
    for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
    setlocal enableDelayedExpansion
    more +!skip! %%F
    endlocal
  )
)