2016-03-04 33 views
0

我想从一个目录复制文件到另一个使用Windows批处理脚本并添加一个时间戳到它。目标目录为空时,它只能使用一次。如果我再次运行批处理脚本,它说在指定的目录中找不到文件。奇怪的是,当我连接原始文件名与时间戳,然后下一次它在源目录中查找连接字符串的文件名。请帮忙。不能复制文件多次使用Windows脚本

@echo off 

for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a 
set YYYY=%dt:~0,4% 
set MM=%dt:~4,2% 
set DD=%dt:~6,2% 
set HH=%dt:~8,2% 
set Min=%dt:~10,2% 
set Sec=%dt:~12,2% 

set stamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec% 

SET "destpath=C:\RatePDF\backup\" 
SET "sourcepath=C:\RatePDF\" 

for /r "%sourcepath%" %%f in (*.xlsx) do (

    SET name=%%~nf 
) 

echo %name% 

SET newFileName = %name%-%stamp% 

COPY "%sourcepath%\%name%.xlsx" "%destpath%\%newFileName%.xlsx" 

pause 
+1

阅读并遵循[调试您的批处理文件](http://www.robvanderwoude.com/battech_debugging.php) – JosefZ

+0

什么@JosefZ说。特别是,在调试**时,首先列出第一件事,并从文件顶部删除'echo off'。那会告诉你哪一行失败! –

回答

1

通过在文件名中插入时间戳来复制文件比大多数人想象的要困难。请参阅Create a backup copy of files以获取详细信息和完整说明。

下面的批处理文件代码应该适用于您的任务将目录C:\RatePDF中的* .xlsx文件与文件名中的当前本地日期和时间复制到子目录backup

@echo off 
rem Note: Remove both /V for copying large files faster without verification. 

setlocal EnableDelayedExpansion 
set "SourcePath=C:\RatePDF" 
if not exist "%SourcePath%\*.xlsx" exit /B 
set "DestPath=%SourcePath%\backup" 

rem Get local date and time in region and language independent format YYYYMMDDHHmmss. 
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS get LocalDateTime /format:value') do set "LocalDateTime=%%I" 

rem Reformat the local date and time to format YYYY-MM-DD_HH-mm-ss. 
set "LocalDateTime=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%-%LocalDateTime:~6,2%_%LocalDateTime:~8,2%-%LocalDateTime:~10,2%-%LocalDateTime:~12,2%" 

rem Command COPY can't be used for copying files with either hidden or 
rem system attribute set or if destination file exists already and has 
rem read-only attribute set. Therefore must use the command XCOPY as this 
rem command can copy also hidden and system files by using option /H, 
rem with keeping the attributes of copied file by using option /K, 
rem with overwriting also already existing file by using option /Y, 
rem even if destination file is read-only by using option /R, 
rem with verifying also successful copying of file by using option /V 
rem and with automatic continuation on failure by using option /C. 

rem But there is a real problem on using XCOPY for copying a single file: 
rem It prompts the user if the destination is a file or a directory if the 
rem destination file does not already exist. And this prompt depends on 
rem language of operating system. 

rem A hack is used to get the language dependent letter from prompt text 
rem without really copying any file. Command XCOPY is used to start copying 
rem the batch file itself to folder for temporary files with file extension 
rem being TMP for destination file. This results in a prompt by XCOPY if 
rem there is not already a file with that name in temporary files folder 
rem which is very unlikely. The handler of device NULL is used as an input 
rem handler for XCOPY resulting in breaking the copying process after the 
rem prompt was output by XCOPY 2 times. This output is processed in a FOR 
rem loop which is exited on first line starting with an opening parenthesis. 
rem This is the line on which second character defines the letter to use 
rem for specifying that destination is a file. 

del /F "%TEMP%\%~n0.tmp" 2>nul 
for /F %%I in ('%SystemRoot%\System32\xcopy.exe "%~f0" "%TEMP%\%~n0.tmp" ^<nul') do (
    set "PromptAnswer=%%I" 
    if "!PromptAnswer:~0,1!" == "(" (
     set "PromptAnswer=!PromptAnswer:~1,1!" 
     goto CreateBackups 
    ) 
) 
echo ERROR: Failed to determine letter for answering prompt of XCOPY. 
exit /B 

:CreateBackups 
if not exist "%DestPath%\" md "%DestPath%" 
rem Note: Files with hidden attribute set are ignored by this FOR loop. 
for %%F in ("%SourcePath%\*.xlsx") do call :CopyFile "%%~F" 
exit /B 

rem Subroutine for copying a single file which always has a file 
rem extension because this batch file is for copying *.xlsx files. 

:CopyFile 
set "FileName=%~n1" 
set "FileExtension=%~x1" 

echo Copy "%~f1" to "%DestPath%\%FileName%_%LocalDateTime%%FileExtension%" 

rem Try to copy the file with standard command COPY with verification. 
copy /V /Y "%~f1" "%DestPath%\%FileName%_%LocalDateTime%%FileExtension%" >nul 2>&1 

rem Copying failed if exit code of COPY is greater or equal 1. 
if errorlevel 1 goto UseXcopy 
echo Success 
exit /B 

rem Another issue to solve is that XCOPY is not reliable on error codes. 
rem For example if option /R would not be used and destination file has 
rem read-only attribute set, the single file copy fails with error message 
rem access denied written to STDERR stream, but the exit code of XCOPY is 
rem nevertheless 0 like on a successful copy. On other errors the exit code 
rem is correct like write access on existing destination file fails because 
rem the destination file is opened currently by an application with blocking 
rem shared access completely or allows just shared read for the file. 

rem So instead of evaluating the exit code, XCOPY is executed within a FOR 
rem loop to evaluate the number of copied files output on last line by XCOPY 
rem to STDOUT stream. The number of copied files is 1 on successful copy of 
rem the single file. Any other string (number 0) is interpreted as failed 
rem copy of the specified file. Output of copied files is suppressed by 
rem using option /Q of XCOPY. 

:UseXcopy 
for /F %%I in ('echo %PromptAnswer% ^| %SystemRoot%\System32\xcopy.exe "%~f1" "%DestPath%\%FileName%_%LocalDateTime%%FileExtension%" /C /H /K /Q /R /V /Y') do set "FilesCopied=%%I" 
if not "%FilesCopied%" == "1" (
    echo ERROR: Creating the backup failed, see error message above. 
    exit /B 
) 
echo Success 
exit /B 

注1:有隐藏属性 *的.xlsx文件不与此批处理文件复制。

注2:批处理文件包含一些行,其中包含echo打印哪个文件被复制以及复制是成功还是失败。一旦批处理文件按预期工作,您应该删除这些行。

您的错误之一是使用/RC:\RatePDF中的所有* .xlsx文件递归复制到C:\RatePDF\backup,因为目标备份目录是源目录的子目录。因此,您的批处理文件会创建副本副本的副本...有问题,不是。

为了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • call /?
  • copy /?
  • del /?
  • echo /?
  • exit /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • rem /?
  • set /?
  • setlocal /?
  • wmic OS get /?

阅读也是微软的文章Using command redirection operatorsTesting for a Specific Error Level in Batch Files

+0

非常感谢!完全按照要求工作。 –

0

我看到两个问题。

首先,您的for /rname设置为您的目录树中发现的最后一个文件名,该目录树创建于sourcedir

由于您的目标目录位于您的源代码树中,因此找到的名称很可能是您在上次运行中创建的文件的名称。

因此,在第一次运行副本sourcepath=C:\RatePDF\file.txtC:\RatePDF\backup\file.txt-2016-03-03-18-36(或类似的东西)

一切优秀和良好,但在第二次运行,检测到最后的文件名会file.txt-2016-03-03-18-36 - 但这是在C:\RatePDF\backup没有`` C:\ RatePDF hence the文件丢失报告。

解决方案:失去/r

下一页问题:

SET newFileName = %name%-%stamp% 

将变量newFileName 空间到的空间%名称%的值 - %邮票%

因此line

COPY "%sourcepath%\%name%.xlsx" "%destpath%\%newFileName%.xlsx" 

将代替没有任何到目标文件名为newfilename,因为它是未定义的。

解决方法:丢失set命令中的两个杂散空间。

+0

感谢您的帮助。但它不起作用。我按照你的说法做了,并且试图通过保持和取消顶部的@echo来实现,但窗口在几秒钟内不断消失。此外,文件根本没有被复制。 mofi的回答提供了帮助。 –