首先,我没有太多编写批处理脚本的经验。在这个和其他网站的帮助下,我写了一些脚本,将文件从几台未连接到网络的PC复制到USB驱动器。现在我想将这些备份文件夹复制到NAS驱动器。备份文件夹的名称均为:
backup_PC1_data1_dd-mm-yyyy
backup_PC1_data2_dd-mm-yyyy
backup_PC2_data1_dd-mm-yyyy
backup_PC2_data2_dd-mm-yyyy
...
NAS驱动器G:\
包含文件夹:
ABC_PC1
ABC_PC2
...
现在我想根据文件夹名称将文件夹从USB驱动器复制到NAS驱动器。
例如:Backup_PC1_data1_tt-mm-yyyy
和Backup_PC1_data2_tt-mm-yyyy
应该复制到NAS驱动器上的文件夹ABC_PC1
,Backup_PC2_data1_tt-mm-yyyy
和Backup_PC2_data2_tt-mm-yyyy
应该复制到该文件夹NAS驱动器上的ABC_PC2
。
由于USB到NAS复制过程应该在不同的PC上运行,而某些PC有多个HDD,我想从USB驱动器启动copy2NAS
脚本。我开始获取驱动器号并设置源驱动器:
set drive=%~d0
set source=%drive%
我的计划是将名为Backup_*
的源中的所有文件夹设置为:
for /d %%i in ("%source%\Backup_*")
然后分割源文件夹的名称并使用Backup_
和_data…
之间的部分来定义目标文件夹(始终G:\ABC_XXX
),其中XXX
是源文件夹名称的Backup_
和_data*
之间的部分。
编写如下代码:
Backup_*
。Backup_
和_data*
之间提取部分。到目前为止我已编码:
set drive=%~d0
set source=%drive%
for /d %%i in (%source%\Backup_*) do call :ProcessDir "%%i"
:ProcessDir
set "foldername=%~n1"
echo %foldername%
for /F "tokens=2 delims=_" %%a in ("%foldername%") do set nthstring=%%a
set "Source=%source%\%foldername%"
set "destination=C:\mol\backups\backup_nas\GMH_%nthstring%\%foldername%"
robocopy %Source% %destination% /s
但看起来这超出了我的批处理脚本技能。我要么最终没有复制过程,要么只是文件到新创建的目的地,或者......
我几乎忘了提到Backup_*
文件夹不是USB驱动器上的唯一文件夹。
有人知道如何实现这项任务吗?
答案 0 :(得分:0)
可以使用以下批处理代码实现:
@echo off
for /D %%I in ("%~d0\backup_*_*") do (
for /F "tokens=2 delims=_" %%J in ("%%~nxI") do (
echo Copying %%I to G:\ABC_%%J ...
%SystemRoot%\System32\xcopy.exe "%%I" "G:\ABC_%%J\%%~nxI\" /C /E /H /I /K /Q /R /Y /Z >nul
)
)
外部 FOR 循环找到因为批处理文件驱动器的根目录中的选项/D
(目录)非隐藏目录,其名称以backup_
并且目录名中至少还有一个下划线。
循环变量I
保存在每个循环上,运行找到的目录名称,其中包含完整路径,该路径从不用双引号括起来。
内部 FOR 只使用引用%%~nxI
的双引号中的字符串获取备份目录的名称。 %%~nI
将被解释为最后一个反斜杠或字符串开头之后的字符串,如果没有反斜杠,但不包括字符串的最后一个点或结尾,如果在最后一个反斜杠/字符串开始后没有任何一点,这意味着名称没有扩展名的目录或文件。 %%~xI
将被解释为从最后一个反斜杠/字符串开始后的最后一个字符串到字符串结尾的字符串,这意味着文件扩展名。因此%%~nxI
是解析后的字符串中字符串的最后一个反斜杠/开始后的字符串,它是文件或目录的整个名称。只有%%~nI
对于目录名称中没有任何一点的目录也就足够了。
内部 FOR 由于选项/F
和第一个(
内的双引号中包含的字符串进行解析... {{1}只是这个字符串。因此,它不会搜索文件,也不会解析命令行的输出,也不会使用选项)
从文本文件中读取行。它只解析两个双引号之间的字符串。
这个作为备份目录名的字符串被拆分成多个字符串,使用下划线字符作为/F
指定的分隔符,而不是默认用作分隔符的空格/制表符。
使用delims=_
指定只需要一个或多个下划线或字符串结尾之间的第二个字符串。
因此,内部循环变量tokens=2
为备份目录示例保留第一个和第二个下划线之间的字符串。
现在确定将USB驱动器上的备份文件夹复制到NAS驱动器上的相应文件夹所需的全部内容。
命令 XCOPY (在Windows XP上也可用)用于将整个备份文件夹及其所有子文件夹和文件复制到NAS驱动器上的文件夹,如果根本不存在,该文件夹甚至会自动创建
将备份文件夹的名称指定为目标文件夹也很重要,否则只会将备份文件夹的文件和子文件夹复制到J
。
使用反斜杠结束目标文件夹也很重要,让命令 XCOPY 知道目标是文件夹而不是文件。在结束时使用反斜杠指定目标时,实际上不需要选项G:\ABC_PCx
。
必须使用命令 DIR 复制备份文件夹中设置了隐藏属性的备份目录:
/I
命令 DIR 返回,因为选项@echo off
for /F %%I in ('dir /AD /B "%~d0\backup_*_*" 2^>nul') do (
for /F "tokens=2 delims=_" %%J in ("%%I") do (
echo Copying %~d0\%%I to G:\ABC_%%J ...
%SystemRoot%\System32\xcopy.exe "%~d0\%%I" "G:\ABC_%%J\%%I\" /C /E /H /I /K /Q /R /Y /Z >nul
)
)
(属性目录)只是与裸文件批处理文件的驱动器根目录中的模式/AD
匹配的目录,因为选项backup_*_*
,这意味着只有没有路径的目录的名称,并且从不用双引号括起来。该目录甚至可以设置隐藏属性。
外部 FOR 由于选项/B
和字符串用单引号在第一个/F
内运行... {{1}此字符串作为命令行执行并处理此命令行输出的每一行以处理 STDOUT 。
内部 FOR 的工作原理如上所述,因为循环变量(
仅包含命令 DIR 没有完整的路径。因此,引用备份目录名称在外部 FOR 的命令块中的所有3个命令中略有不同。
)
将 DIR 输出的错误消息重定向到执行 FOR 到句柄 STDERR 到设备 NUL 来压制它。如果找不到任何备份目录,则 DIR 会输出令人困惑的错误消息。这里有必要用I
转义2^>nul
,以便稍后在执行 DIR 时将此字符解释为重定向运算符,而不是在解析 FOR 命令行。仅使用命令行中的>
执行 FOR 将导致批处理退出,因为语法错误。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
^
2>nul
dir /?
echo /?
另请参阅Microsoft文章Using command redirection operators。