【问题标题】:Batch file to rename a subfolder according to subfolder name批处理文件根据子文件夹名称重命名子文件夹
【发布时间】:2016-09-11 19:06:18
【问题描述】:

我是批处理脚本的新手,我需要帮助来解决这个重复的手动任务。我需要使用批处理文件自动化

我的目录结构如下例

c:\machines\models\a\defects
c:\machines\models\b\defects
c:\machines\models\c\defects
c:\machines\models\d\defects
and it continues e, f, g, h

(a、b、c、d 只是示例,机器会根据我们测试的模型生成文件夹)

我想移动缺陷文件夹的内容(包括其中的子文件夹和文件) 到具有以下内容的目标文件夹: 1. 当前日期 2.根据它的模型重命名缺陷文件夹,如下所示,使用批处理文件(ms dos)

e:\backup\currentdate\a_defects
e:\backup\currentdate\b_defects
e:\backup\currentdate\c_defects
e:\backup\currentdate\d_defects

请帮忙!

【问题讨论】:

  • 欢迎来到 SO 。请阅读minimal reproducible example。请在此处输入一些代码..
  • 感谢 sjsam。一旦我擅长批处理代码,就会在这里放一些代码:)
  • 如果不尝试(和错误:)),你就无法擅长批量编码

标签: batch-file cmd


【解决方案1】:

这是此任务的注释批处理代码:

@echo off
setlocal

rem Define source and backup path.
set "SourcePath=C:\machines\models"
set "BackupPath=E:\backup"

rem Get current date in format YYYY-MM-DD independent on local date format.
for /F "skip=1 tokens=1 delims=." %%T in ('%SystemRoot%\System32\wbem\wmic.exe OS get localdatetime') do set LocalDateTime=%%T & goto ReformatDate
:ReformatDate
set "YearMonthDay=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%-%LocalDateTime:~6,2%

rem For each subfolder in source path check if there is a subfolder "defects".
rem If subfolder "defects" exists, copy all files and subfolders of "defects"
rem to the appropriate backup directory with current date and subfolder name
rem in source folder path. Then remove the subfolder "defects" in source
rem folder even if being completely empty to avoid processing this folder
rem again when not being recreated again in the meantime.

for /D %%# in ("%SourcePath%\*") do (
    if exist "%%#\defects\*" (
        %SystemRoot%\System32\xcopy.exe "%%#\defects\*" "%BackupPath%\%YearMonthDay%\%%~nx#_defects\" /H /I /K /Q /R /S /Y >nul
        rd /Q /S "%%#\defects"
    )
)
endlocal

在命令提示符窗口wmic OS get localdatetime 中运行一次以查看此命令输出的内容,以更好地了解当前日期是如何以YYYY-MM-DD 格式确定的。使用%DATE% 会更快,但%DATE% 的日期字符串格式取决于Windows 区域和语言设置中设置的国家/地区,因此需要了解运行此批处理文件的计算机上的日期字符串格式。

如果models 目录中有defects 子文件夹,则带有使用选项的命令XCOPY 不会在备份目录中创建子文件夹,但在整个defects 子文件夹树中存在至少要复制 1 个文件。

使用环境变量 DATE 的替代代码,期望扩展的日期字符串以:MM/DD/YYYY 结尾,例如Tue 05/17/2016,详细解释于:
What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?

@echo off
setlocal

rem Define source and backup path.
set "SourcePath=C:\machines\models"
set "BackupPath=E:\backup"

rem Get current date in format YYYY-MM-DD depending on local date format.
set "YearMonthDay=%DATE:~-4,4%-%DATE:~-10,2%-%DATE:~-7,2%"

rem For each subfolder in source path check if there is a subfolder "defects".
rem If subfolder "defects" exists, copy all files and subfolders of "defects"
rem to the appropriate backup directory with current date and subfolder name
rem in source folder path. Then remove the subfolder "defects" in source
rem folder even if being completely empty to avoid processing this folder
rem again when not being recreated again in the meantime.

for /D %%# in ("%SourcePath%\*") do (
    if exist "%%#\defects\*" (
        %SystemRoot%\System32\xcopy.exe "%%#\defects\*" "%BackupPath%\%YearMonthDay%\%%~nx#_defects\" /H /I /K /Q /R /S /Y >nul
        rd /Q /S "%%#\defects"
    )
)
endlocal

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

  • echo /?
  • endlocal /?
  • for /? ... 还解释了 %%~nx#(模型子文件夹的名称(和扩展名))。
  • if /?
  • rd /?
  • set /?
  • setlocal /?
  • wmic.exe OS get /?
  • xcopy /?

另请参阅有关Using command redirection operators 的Microsoft 文章以了解>nul 的含义。

为什么%%~nx# 而不仅仅是%%~n# 因为文件夹没有文件扩展名

Windows 命令处理器无法确定字符串是文件夹还是文件名。最后一个反斜杠之后的所有内容都被解释为文件名,独立于文件或文件夹的真实名称。并且字符串中最后一个反斜杠之后的最后一个点之后的所有内容都被解释为 文件扩展名,即使这意味着使用 %~n 引用的文件夹或文件名是一个空字符串,因为文件夹/文件名以dot 并且不像 *nix 系统上的许多“隐藏”文件那样包含一个点,例如.htaccess。因此,如果在命令行中需要文件夹或文件的全名,则应始终使用%~nx

【讨论】:

  • 好的,echo %DATE% 的输出是星期二 05/17/。有没有更好的方法将日期用作目录。我更喜欢使用日期,我会搜索并阅读您提供的链接。谢谢:)
  • 为由环境变量 DATEabbreviated weekday MM/DD/YYYY 格式确定的目录名称添加了具有当前日期的备用批处理代码,格式为 YYYY-MM-DD,例如Tue 05/17/2016.
【解决方案2】:

这是 我的 注释代码。 Mofi 更快(没有老人的网站......)

使用robocopy command 而不是deprecated xcopy

注意/L 切换到robocopy 命令:仅列出 - 不要复制、添加时间戳或删除任何文件。在调试之前移除/L 开关。

@ECHO OFF
SETLOCAL EnableExtensions
rem obtain %_currentdate% variable in locale independent yyyymmdd format
for /f "tokens=2 delims==" %%G in (
  'wmic OS get localdatetime /value^|find "="') do set "_currentdate=%%G"
set "_currentdate=%_currentdate:~0,8%"
rem show %_currentdate% variable for debugging purposes
set _currentdate

rem appoint source and target directories
set "_sourcedir=c:\machines\models"
set "_targetdir=E:\backup\%_currentdate%"

for /F "delims=" %%G in ('dir /B /AD "%_sourcedir%\"') do (
  set "_notEmpty="
  rem check if `defects` folder exists 
  if exist "%_sourcedir%\%%G\defects\*" (
    rem credit and tribute to DBenham in https://*.com/a/10818854/3439404
    rem check if a folder contains at least one file 
    >nul 2>nul dir /a-d "%_sourcedir%\%%G\defects\*" && (set "_notEmpty=f")
    rem check if a folder or any of its descendents contain at least one file
    >nul 2>nul dir /a-d /s "%_sourcedir%\%%G\defects\*" && (set "_notEmpty=f")

    if defined _notEmpty (
        rem create target directory silently; suppress error message 'already exists'
        md "%_targetdir%\%%G_defects\" >NUL 2>&1

        rem move content of %_sourcedir%\%%G\defects\* to %_targetdir%\%%G_defects\
        robocopy "%_sourcedir%\%%G\defects" "%_targetdir%\%%G_defects" /S /E /MOVE /L

        rem recreate source directory deleted (moved) by robocopy 
        md "%_sourcedir%\%%G\defects\" >NUL 2>&1
    ) else (
        echo nothing to do in %_sourcedir%\%%G\defects
    )
  ) else (
      echo nothing to do in %_sourcedir%\%%G
  )
)

感谢this answer 中的 DBenham(检查文件夹是否为空)。

【讨论】:

  • 嗨@josefZ,很遗憾机器(XP)不支持robocopy,感谢您的帮助。将研究您的代码,因为它可能有助于将来的批处理代码。感谢您的帮助:)
最近更新 更多