2

我创建了一个批处理文件,它将文件和子文件夹从源复制到目标。我已经压制了各种错误。以下是我目前正在使用的代码:

Echo ****Copying...****
XCOPY "C:\Users\xxxxxx\Desktop\Source" "D:\xxxxx\Destination" /S /E /V /Y /R /C
Echo ****Files Copied Successfully...****
PAUSE

现在我想做的是,一旦文件复制完成,它应该显示由于某些错误而未复制到目标的所有文件的列表。

提前致谢...

4

2 回答 2

1

使用命令将输出和错误重定向到一个文件,>logfile.txt 2>&1然后对其进行后处理:logfile.txtfor /F

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion
set "source=d:\bat\*.txt"
set "target=d:\xxx\ddd"
xcopy "%source%" "%target%" /i /s /e /y /c>%temp%\xcopyall.txt 2>&1

set /A "goodfiles=-1"
set /A "bad_files=0"

set "filename=%source:~0,2%"
set "errdescr=%filename%"
for /f "tokens=* delims=)(" %%G in ('type "%temp%\xcopyall.txt"') do (
  set "errdescr=%%G"
  call :posterr 
)
echo %bad_files% File[s] not copied
:::: %goodfiles% File[s] copied
@ENDLOCAL
goto :eof

:posterr
set "errdescr=%errdescr:(=[%"  
set "errdescr=%errdescr:)=]%"
rem previous line == a filename?  
if /i "%filename:~0,2%"=="%source:~0,2%" (
  rem current line == a filename?
  if /i "%errdescr:~0,2%"=="%source:~0,2%" (
      set /A "goodfiles+=1"
  ) else (
      rem rem current line == 'nnn File[s] copied'?
      if /i "%errdescr:File[s] copied=%"=="%errdescr%" (
        set /A "bad_files+=1"
        echo %filename:&=^&% %errdescr:&=^&%
    ) else ( 
        set /A "goodfiles+=1"
    )
  )
)
set "filename=%errdescr%"
goto :eof

固定

  • 参加日志文件的结尾,即nnn File(s) copied文本
  • "d:"由动态替换的文字值"%source:~0,2%"
  • 具有改进的测试逻辑的两个(未)复制项目的辅助计数器(参见代码中的注释)
  • 借助dbenham测试了包含!, %,的文件名(请参阅输出) ,谢谢...&

该脚本仍然可能显得不够充分,可以针对可能的更复杂的场景对其进行改进(仅在目标端测试访问被拒绝错误)。

输出

d:\bat>vbserr2
D:\bat\CPs2\unicMacCE.txt Access denied
D:\bat\files\11per%cent.txt Access denied
D:\bat\files\12per%cent%.txt Access denied
D:\bat\files\13per%OS%cent.txt Access denied
D:\bat\files\14per%%OS%%cent.txt Access denied
D:\bat\files\15per%3cent.txt Access denied
D:\bat\files\16per%%3cent.txt Access denied
D:\bat\files\17per%Gcent.txt Access denied
D:\bat\files\18per%%Gcent.txt Access denied
D:\bat\files\1exclam!ation.txt Access denied
D:\bat\files\21ampers&nd.txt Access denied
D:\bat\files\22ampers&&nd.txt Access denied
D:\bat\files\2exc!lam!ation.txt Access denied
D:\bat\files\rand.txt Access denied
14 File[s] not copied

但是,Xcopy已被弃用(尽管现在仍然可用)。请改用其他工具(例如Robocopy)。

于 2015-01-12T12:59:29.377 回答
0

您可以通过查找后跟不以数字开头且第二个字符不是冒号的另一行的行来检测文件是否错误。

为了以编程方式执行此操作,您必须将 stderr 重定向到 stdout 2>&1,以便在一个流中获取所有数据。

JosefZ将所有内容重定向到一个文件,并使用 FOR /F 循环进行后处理以提取错误消息。

下面是一个更有效的解决方案,将输出通过管道传输到JREPL.BAT - 一种混合 JScript/批处理实用程序,可对文本执行正则表达式搜索/替换。JREPL.BAT 是纯脚本,可​​以在从 XP 开始的任何 Windows 机器上本地运行。

xcopy "C:\Users\xxxxxx\Desktop\Source" "D:\xxxxx\Destination" /s /e /v /y /r /c /I 2>&1 | ^
jrepl "^(.+\n)(\D[^:][^\r\n]*)\r\n/^.*\n" "'***'+$3+': '+$2/stderr.Write($0);''" /m /j /t "/"

我使用续行只是为了使代码更易于阅读。

  • /M 选项允许搜索跨越多行。
  • /J 选项将替换值视为 JScript 代码
  • /T 选项类似于 unix tr 命令。搜索和替换参数都包含相同数量的值,由 . 分隔/。如果第一个搜索词匹配,则使用第一个替换值,否则第二个替换值用于第二个搜索词。

第一个搜索词查找文件名,然后是错误消息。如果找到,则将这两行替换为使用格式的单行***eror message: filePath。由于这是多行搜索,因此在完成整个搜索/替换之前不会显示结果。

第二个搜索词(仅在第一次匹配失败时使用)仅匹配整行。在将值替换为空字符串之前,此行会立即输出到 stderr。

最终结果是成功的文件和摘要首先使用 stderr 输出到控制台,然后是错误文件和 stdout 上的错误消息。

下面是一个测试样本输出:

D:test.bat
D:test.js
D:test.log
D:test.txt
D:test.txt.bad
D:test.vbs
D:test2.bat
D:test3.bat
D:test\test(1).txt
D:test\test(10).txt
D:test\test(11).txt
D:test\test(2).txt
D:test\test(3).txt
D:test\test(5).txt
D:test\test(6).txt
D:test\test(7).txt
D:test\test(8).txt
D:test\test(9).txt
D:test\test.txt
19 File(s) copied
***Access denied: D:test.csv
***Access denied: D:test\test(4).txt

输出是低音确认,因为错误消息在标准输出上,成功消息在标准错误上。

如果需要,您可以通过附加将整个结果捕获到日志文件中>xcopy.log 2>&1

或者您可以使用>xcopy.err 2>xcopy.log.

于 2015-01-12T15:23:31.377 回答