在 windows 批次中将目录+路径复制到新位置(使用 robocopy)

Copying directory+path to new location in windows batch (using robocopy)

我正在尝试将我收到的脚本中的一部分复制标准化。

因此,最好重新编写以下块:

REM Copy files
for %%x in (%var1%) do (
    copy %src%\%%x %dest%\%%x
)

其中 var1 包含格式为 folder\folder\file.fileExtension 的字符串,因此示例为:

var1=test\test1\test1.txt test\test1\test2.txt test\test3\randomfile.cmd

目的地还不存在(目前只是单独创建的)。

不幸的是 robocopy 不会以这种方式复制(它不会接受格式 folder\filefolder\file 作为我所看到的源和目标)。这意味着我需要将最后一个反斜杠处的变量分成两个变量或使用不同的复制工具(如 copyxcopy),但这是 "discouraged".

有没有人有巧妙的方法让 robocopy 接受这种格式,而无需创建新函数将传递的变量分成两个新变量?或者是否有不同的方法来存储可消除此问题的 folder\file 路径的可迭代列表?

我已经能够从给定 %%~n 的传递参数中检索名称部分,但无法检索传递参数的路径部分,因为它不是完整路径。我试图使用 for 循环来切断该部分(类似于此处的结果:Last token in batch variable

这是行不通的,因为它是一个 \ 分隔的字符串,据我所知,您不能在 for /f.

中以 FOREACH 样式循环

考虑到您提到的 for 块,您可以通过以下方式将 copy 替换为 robocopy 命令:

for %%v in (%listOfFiles%) do (robocopy %%~dv%%~pv %destinationPath% %%~nv%%~xv)

评论中已经提到,%%~dv%%~pv%%~nv%%~xv分别是扩展磁盘、路径(不包括磁盘)的语句, %%v 变量的名称和扩展名。当然,这种扩展只适用于指向文件路径的变量。最后,robocopy 命令的语法至少需要一个源路径、一个目标路径和一个要复制的文件列表。那么,如果之前定义了目标路径,脚本应该可以正常工作。

编辑 n.r 1
如果在 %listOfFiles% 文件中没有列出完整路径而只列出了其中的一部分,您可以使用 * 字符尝试以正确的方式填写它。此功能的一个简单示例可以是:

C:\Users\username>cd D*p
C:\Users\username\Desktop>_

以下代码可能适合您(有关简要说明,请参阅 rem 备注):

rem define source and destination roots here (no trailing `\` allowed!):
set "src=D:\path\to\source\dir"
set "dst=D:\path\to\destin\dir"
rem define list of items here:
set var1="test\test1\test1.txt" "test\test1\test2.txt" "test\test3\randomfile.cmd"

setlocal EnableDelayedExpansion
for %%I in (%var1%) do (
    rem append variable item to source and destination roots,
    rem and append a `|` which is not allowed in file names:
    set "src=%src%\%%~I|"
    set "dst=%dst%\%%~I|"
    rem truncate only LAST item (name+ext.) and `|` from the paths:
    set "src=!src:%%~nxI|=!"
    set "dst=!dst:%%~nxI|=!"
    rem supply paths with trailing `\` removed and LAST item (name+ext.) to `robocopy`:
    robocopy "!src:~,-1!" "!dst:~,-1!" "%%~nxI"
)
endlocal

您可能会注意到,临时附加了一个管道符号 |,这是文件路径的禁用字符。这样做是为了即使所有受影响的树中的一个或多个目录与任何复制的文件同名(test1.txttest2.txtrandomfile.cmd 在示例中)。

这是我使用的完整解决方案,与 aschipfl 发布的内容非常相似(我从我的实际脚本中修改了其他内容以使其更有意义 - robocopy wrapper 是一个处理 robocopy 错误的包装脚本例如,更改变量名称更好):

.....

REM Copy SWFs
set src=%SV1%\%V2%\%V3%
set dest=.\%DV1%\%V2%\%V3%
call :doPatchSWFFileCopy

set src=%SV1%\%V2%\%V3%
set dest=.\%DV1%\%DV2%\%V3%
call :doPatchSWFFileCopy

.....

:doPatchSWFFileCopy
SETLOCAL EnableDelayedExpansion
for %%I in (%_filelist_%) do (
    REM Append file path to source and dest, as well as a pipe to prevent same name copies
    set "src=%src%\%%~I|"
    set "dest=%dest%\%%~I|"
    REM Truncate only LAST item (file name + extension) and the pipe character from the paths:
    set "src=!src:%%~nxI|=!"
    set "dest=!dest:%%~nxI|=!"
    REM truncate trailing slash
    call %robocopywrapper% "!src:~,-1!" "!dest:~,-1!" "%%~nxI"
)
ENDLOCAL
goto :EOF