批处理文件:从日志文件中读取最后一行并将它们复制到一个新文件中
Batchfile: read last lines from logfiles and copy them to a new 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 个条目,但它 returns 每个日志文件的每一行:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
我需要的是两者的组合,但我不知道如何组合它们并将完整的最后一行复制到 .csv 文件。
===
@马古:
感谢您的反应。
在每个日志文件中可以有 1 到 >100 行以逗号分隔的信息。类似于:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
第 4 个条目的最后一个代码用于获取已登录计算机的所有帐户的列表。此代码为我提供了一个非常大的列表,其中包含我在 %list% 中检查的所有计算机日志中的所有 logon/logoff 事件。
在 %list$ 中,我有我想要检查的所有日志文件的名称。这返回了所有行。
对于新的批处理文件,我只需要最后一个 logon/logoff 条目并且我想要整个最后一行。
所以我有一个 .txt 文件,其中包含我需要检查的所有计算机的主机名。
将通过变量 %list%.
逐行读取此 .txt 文件。
我只需要将每个日志文件的最后一行复制到输出文件。
===
我刚刚尝试了 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
如果文件有更多尾随空行,您的行编号方法可能会失败。幸运的是 for /F
循环忽略(不迭代)空行;让我们开始使用这个功能:在脚本中使用接下来的做法:
disabledelayedexpansion
允许在文件名中使用 !
set "list=_listing.txt"
其中 _listing.txt
包含文件名列表(包括完整路径和扩展名 .txt
),一行一个文件名:由 dir /b /s *.txt>_listing.txt
[ 获取=50=]
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\filesexclam!ation.txt
d:\bat\filesexc!lam!ation.txt
d:\bat\filesper%cent.txt
d:\bat\filesper%cent%.txt
d:\bat\filesper%Gcent.txt
d:\bat\filesper%%Gcent.txt
d:\bat\filesampers&nd.txt
d:\bat\filesampers&&nd.txt
输出:
d:\bat>lastlines
d:\bat\filesexclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\filesexc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\filesper%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\filesper%cent%.txt !!!file empty!!!
d:\bat\filesper%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\filesper%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\filesampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\filesampers&&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
您应该使用简单的 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
)
)
如果您的任何文件名包含 !
字符,那么您必须在循环中打开和关闭延迟扩展。否则延迟扩展会在扩展 %%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
)
)
这是我的第一篇文章,所以如果格式不符合预期,请原谅。 (
的建议欢迎改进。)
我正在尝试创建一个批处理文件,它将从日志文件中读取最后几行并将它们复制到一个新文件中。
到目前为止,我已经找到 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 个条目,但它 returns 每个日志文件的每一行:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
我需要的是两者的组合,但我不知道如何组合它们并将完整的最后一行复制到 .csv 文件。
=== @马古: 感谢您的反应。 在每个日志文件中可以有 1 到 >100 行以逗号分隔的信息。类似于:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
第 4 个条目的最后一个代码用于获取已登录计算机的所有帐户的列表。此代码为我提供了一个非常大的列表,其中包含我在 %list% 中检查的所有计算机日志中的所有 logon/logoff 事件。 在 %list$ 中,我有我想要检查的所有日志文件的名称。这返回了所有行。
对于新的批处理文件,我只需要最后一个 logon/logoff 条目并且我想要整个最后一行。
所以我有一个 .txt 文件,其中包含我需要检查的所有计算机的主机名。 将通过变量 %list%.
逐行读取此 .txt 文件。我只需要将每个日志文件的最后一行复制到输出文件。
=== 我刚刚尝试了 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
如果文件有更多尾随空行,您的行编号方法可能会失败。幸运的是 for /F
循环忽略(不迭代)空行;让我们开始使用这个功能:在脚本中使用接下来的做法:
disabledelayedexpansion
允许在文件名中使用!
set "list=_listing.txt"
其中_listing.txt
包含文件名列表(包括完整路径和扩展名.txt
),一行一个文件名:由dir /b /s *.txt>_listing.txt
[ 获取=50=]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\filesexclam!ation.txt
d:\bat\filesexc!lam!ation.txt
d:\bat\filesper%cent.txt
d:\bat\filesper%cent%.txt
d:\bat\filesper%Gcent.txt
d:\bat\filesper%%Gcent.txt
d:\bat\filesampers&nd.txt
d:\bat\filesampers&&nd.txt
输出:
d:\bat>lastlines
d:\bat\filesexclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\filesexc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\filesper%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\filesper%cent%.txt !!!file empty!!!
d:\bat\filesper%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\filesper%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\filesampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\filesampers&&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
您应该使用简单的 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
)
)
如果您的任何文件名包含 !
字符,那么您必须在循环中打开和关闭延迟扩展。否则延迟扩展会在扩展 %%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
)
)