It's normal to follow the @echo off
line with setlocal
. This makes sure that any variables altered or created in the batch file are not maintained in the cmd
session's environment when the batch ends.
Use set "var=value"
for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \
, Space or "
- build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value"
is used, then the quotes become part of the value assigned.
The set drive=...
statement will include the space following the =
in the value assigned to drive
. This is probably of no consequence in the current situation, but may be significant for other batches.
Other than the last 2 lines of code, there is a great deal of date/time-manipulation going on. We have to rely on your local knowledge here as the date/time format is user-dependent.
The overall problem is that *
cannot be used for directorynames. Logically, what you appear to want to copy from your description is ...e_projects\PWD\*100\*
, but that structure is not supported by xcopy
.
So I'll restate the problem as "copy all directories that have a name ending 100
"
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the directories and filenames are names
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
FOR /f "delims=" %%e IN (
'dir /b /s /ad "%sourcedir%\PWD\*" ^|findstr /e "100"'
) DO (
SET "dirname=%%e"
SET "dirname=!dirname:*\PWD\=!"
ECHO XCOPY "%%e\*" "%destdir%\!dirname!\"
)
GOTO :EOF
Always verify against a test directory before applying to real data.
The setlocal enabledelayedexpansion
invokes delayedexpansion
mode, where within a code block (parenthesised sequence of lines) !var!
is the run-time value of var
(as var
is changed) and %var%
is the value that var
contained when the code block was parsed.
Documentation: Stephan's DELAYEDEXPANSION link
We then establish the source and destination directories. I've posted my test directories, you would need to edit them to suit your particular circumstances.
The dir
command lists all directories (/ad
) in basic form (/b
) that is, name only - no size, date, etc. The /s
extends the scan to subdirectories also.
The dir
output is piped to findstr
(the caret escapes the pipe to show that it is part of the command to be executed, not of the for
) which filters the dir
list for (directorynames) which /e
end "100".
The for/f
assigns each line of the result to %%e
. The delims=" ensures the entire line is assigned to
%%e(in case
%%e` contains separators like Space)
%%e
thus contains something like U:\your files\PWD\sub 5\subsub 5\subsubsub\subsubsubsub100
, so we need to remove the part up to \PWD\
to get the subdirectory name in a format suitable for the xcopy
command. Batch cannot substring a metavariable
like %%e
directly, so we assign %%e
to a user-variable dirname
(which is therefore changing within the loop, so we need to use !dirname!
to acess it's run-time value) and the following set
removes all characters up to and including \PWD\
. (See set /?
from the prompt for documentation)
Then it's just a matter of performing the xcopy
. Note that I've added an echo
keyword to "disarm" the xcopy
so that the xcopy
command is merely listed to the console instead of being executed. Once you've verified that the command is correct, remove that echo
to actually execute the xcopy
.
The destination of the xcopy
is </kbd> which tells xcopy
that the destination is a directory, and to create it if it does not exist.
Add >nul
to the xcopy
command to suppress the report if you want.