根据文件夹名称中的第二个下划线分隔部分将文件夹批量复制到变量目标

时间:2016-12-13 23:43:34

标签: windows batch-file cmd

首先,我没有太多编写批处理脚本的经验。在这个和其他网站的帮助下,我写了一些脚本,将文件从几台未连接到网络的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-yyyyBackup_PC1_data2_tt-mm-yyyy应该复制到NAS驱动器上的文件夹ABC_PC1Backup_PC2_data1_tt-mm-yyyyBackup_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*之间的部分。

编写如下代码:

  • 对于USB驱动器上的所有文件夹,请检查名称是否为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驱动器上的唯一文件夹。

有人知道如何实现这项任务吗?

1 个答案:

答案 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