-4

I am new to batch scripting, I need help to solve this repeating manual task. I need to automate using batch file

I have this directories structures as below example

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 is just example as machines will generate the folders according to models we test)

I would like to move the defects folder contents (includes subfolders & files inside it) to a destination folders that have: 1. Current date 2. rename defects folder according to it models as shown in below desired output using batch file (ms dos)

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

Kindly please help!

N Ketam
  • 3
  • 3

2 Answers2

1

Here is a commented batch code for this task:

@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

Run once in command prompt window wmic OS get localdatetime to see what this command outputs to understand better how the current date is determined in format YYYY-MM-DD. It would be faster to use %DATE%, but the format of date string of %DATE% depends on the country set in Windows region and language settings and therefore requires knowledge of date string format on computer running this batch file.

The command XCOPY with the used options does not create the subfolder in backup directory if there is a defects subfolder in a models directory, but in entire defects subfolder tree there is not at least 1 file to copy.

Alternate code using environment variable DATE with expecting that the expanded date string ends with: MM/DD/YYYY, e.g. Tue 05/17/2016, explained in detail in answer on:
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

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • for /? ... explains also %%~nx# (name (and extension) of models subfolder).
  • if /?
  • rd /?
  • set /?
  • setlocal /?
  • wmic.exe OS get /?
  • xcopy /?

See also the Microsoft article about Using command redirection operators to understand the meaning of >nul.

Why %%~nx# and not just %%~n# as a folder does not have a file extension?

Windows command processor does not determine if a string is a folder or a file name. Everything after last backslash is interpreted as file name independent on being in real the name of a file or a folder. And everything after last dot after last backslash in string is interpreted as file extension even if this means that the folder or file name referenced with %~n is an empty string because the folder/file name starts with a dot and does not contain one more dot like many "hidden" files on *nix systems have, e.g. .htaccess. Therefore %~nx should be always used if entire name of a folder or file is needed on a command line.

Community
  • 1
  • 1
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Ok the output for echo %DATE% is Tue 05/17/. Is there any better way on using date as a directory. I prefer using date, I will search around and read the links that you gave. Thanks :) – N Ketam May 17 '16 at 00:25
  • Added an alternate batch code with current date in format `YYYY-MM-DD` for directory name determined from environment variable __DATE__ in format `abbreviated weekday MM/DD/YYYY`, e.g. `Tue 05/17/2016`. – Mofi May 17 '16 at 05:53
0

Here's my commented code. Mofi is faster (No Site for Old Men…)

Using robocopy command rather than deprecated xcopy.

Note /L switch in robocopy command: List only - don’t copy, timestamp or delete any files. Remove /L switch no sooner than debugged.

@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://stackoverflow.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
  )
)

Credit and tribute to DBenham in this answer (check if a folder is or isn't empty).

Community
  • 1
  • 1
JosefZ
  • 28,460
  • 5
  • 44
  • 83
  • Hi @josefZ, unfortunately the machine (XP) does not support the robocopy, I appreciate your help. Will study your code as it might help in future batch code. Appreciated your help :) – N Ketam May 17 '16 at 02:46