从批处理文件中重定向输出


110

我正在使用一些简单的命令创建一个批处理文件,以从系统中收集信息。批处理文件包含用于获取时间,IP信息,用户等的命令。

我将所有命令组装在一个批处理文件中,并且可以运行,但是我希望该批处理文件在运行时将结果输出到文本文件(日志)。是否可以添加到批处理中的命令?

请记住,我不想从cmd运行批处理,然后重定向输出;如果可能的话,我想从批处理内部重定向输出。

Answers:


161

一种简单的天真方法,它很慢,因为它多次打开和定位指向文件尾的文件指针。

@echo off
command1 >output.txt
command2 >>output.txt
...
commandN >>output.txt

更好的方法-更容易编写,并且速度更快,因为文件仅打开和定位一次。

@echo off
>output.txt (
  command1
  command2
  ...
  commandN
)

另一种好又快的方法是只打开和定位文件一次

@echo off
call :sub >output.txt
exit /b

:sub
command1
command2
...
commandN

编辑2020-04-17

您可能不时地要反复写入两个或更多文件。您可能还希望屏幕上显示不同的消息。通过重定向到带括号的块或子例程之外的未定义句柄,然后使用该&符号引用已打开的文件,仍然可以有效地做到这一点。

call :sub 9>File1.txt 8>File2.txt
exit /b

:sub
echo Screen message 1
>&9 File 1 message 1
>&8 File 2 message 1
echo Screen message 2
>&9 File 1 message 2
>&8 File 2 message 2
exit /b

我选择以相反的顺序使用句柄9和8,因为在同一命令上执行多个重定向时,由于Microsoft重定向实现设计缺陷,这种方式更有可能避免潜在的永久重定向。这是极不可能的,但是如果您尝试足够的话,即使采用这种方法也可能会暴露该错误。如果您进行重定向,则可以避免该问题。

3>File1.txt ( 4>File2.txt call :sub)
exit /b

:sub
etc.

2
喜欢可以在其余文件中进行设置的解决方案
Sam

3
请注意,呼叫解决方案会将您的%0(在这种情况下更改为sub)更改为您想要或不想要的。
Jannes '16

1
@Jannes-是的,但是如果添加修饰符,则始终可以获得有关正在运行的批处理脚本的信息。例如,%~f0即使在CALLed:subroutine中,也始终提供批处理脚本的完整路径。
dbenham

3
@ThariqNugrohotomo-– >output.txt 2>&1
dbenham

2
@Moondra-这是用于在同一脚本中调用带标签的子例程的标准批处理语法。执行cmd /?help cmd从控制台命令行获取文档。第三种方法的窍门是CALL上的重定向适用于CALLed子例程中的所有命令。
dbenham


16

我知道这是一篇较旧的文章,但是有人会在Google搜索中偶然发现它,而且看来OP在评论中提出的一些问题并未得到特别解决。另外,请放轻松,因为这是我在SO上发布的第一个答案。:)

为了使用动态生成的文件名将输出重定向到文件,@ dbenham提供的第二种解决方案是我的常用方法(阅读:快速又肮脏)。因此,例如:

@echo off
> filename_prefix-%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log (
echo Your Name Here
echo Beginning Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
REM do some stuff here
echo Your Name Here
echo Ending Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
)

将创建一个类似于您在此看到的文件 在目标目录屏幕快照中

这将包含以下输出:

Your Name Here
Beginning Date/Time: 2016-09-16_141048.log
Your Name Here
Ending Date/Time: 2016-09-16_141048.log

另外请记住,此解决方案取决于语言环境,因此请谨慎使用方式。


谢谢,这很有用。快速的问题是您使用.log和.txt的原因吗?这有什么区别吗?
Moondra

1
@Moondra不,不是。在这种情况下只是语义。这并不是说没有基于文件类型的要求/ grep的应用程序,所以只要知道是否/如何使用您的文件即可。
安东尼

9
echo some output >"your logfile"

要么

(
 echo some output
 echo more output
)>"Your logfile"

应该付账单。

如果要APPEND输出,请使用>>代替>>将启动一个新的日志文件。


9
@echo off
>output.txt (
echo Checking your system infor, Please wating...

systeminfo | findstr /c:"Host Name" 
systeminfo | findstr /c:"Domain"

ipconfig /all | find "Physical Address" 

ipconfig | find "IPv4" 
ipconfig | find "Default Gateway"

)

@pause

我认为这是最优雅的方式。谢谢韦斯利!
Kiswanij

5

有一个很酷的小程序,您可以用来将输出重定向到文件和控制台

some_command  ^|  TEE.BAT  [ -a ]  filename 


3
@echo OFF
[your command] >> [Your log file name].txt

我在批处理文件中使用了上面的命令,它可以正常工作。在日志文件中,它显示了我的命令的结果。


3

将这两行添加到批处理文件顶部附近,之后的所有stdout和stderr都将重定向到log.txt:

if not "%1"=="STDOUT_TO_FILE"  %0 STDOUT_TO_FILE %*  >log.txt 2>&1
shift /1

这对我有用,谢谢。有什么特殊的考虑可能会失败吗?(例如,输出大小溢出)
CCarlos

嗨,谢谢您的回答!还有什么办法可以在控制台上重定向它吗?
Sandeep Singh

0

在输入中出现“有毒”字符的情况下,这可能会失败。考虑这样的输入IsAnIn ^^^^ put是一种很好的方式来了解正在发生的事情。当然,有一个规则是输入字符串必须在双引号中,但是我有一个感觉,只有当输入的含义是NTFS分区上的位置时,该规则才是有效的规则(也许这是URL的规则)不确定)。但这当然不是任意输入字符串的规则(这是“一种很好的做法”,但您不能指望它)。


0

在批处理文件底部添加以下几行,即可抓取CMD窗口中显示的所有内容,并将其导出到文本文件中:

powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard > MyLog.txt

它基本上执行全选 -> 复制到剪贴板 -> 粘贴到文本文件中

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.