Reputation: 23
I have a folder structure like his
folder1-------|
|123456------123.txt
abc.txt
|234567------fgt.txt
234.txt
|abc---------ytr.txt
1234.txt
I need to copy files from Main folders sub directories if the sub folder has a length of 6(only numbers) . So .txt files from 123456,234567 will be copied and abc will not be copied.
I have tried using wildcards but not succeed yet. Thanks in advance.
>xcopy /s "C:\Users\xxx.xxx\Desktop\folder1\*\*.txt" "C:\Users\xxx.xxx\Documents\New folder" /l /D:09-09-2019
Upvotes: 1
Views: 329
Reputation:
Ok, so here is an example:
@echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir "C:\Users\xxx.xxx\Desktop\folder1\" /b /ad') do (
set "str=#%%i"
set "len=0"
for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!str:~%%a,1!" neq "" (
set /a "len+=%%a"
set "str=!str:~%%a!"
if !len! equ 6 if 1%%i equ +1%%i echo %%i is !len! characters
)
)
)
This will do a dir
of the directories inside the path you give it. It will then test the length of the string, if the length is 6 characters, it will then test if the string is numeric, if true, it will echo
the string (folder name) and the length of it. You should then test it as is and if it gives you the required output, you can replace echo
portion with your copy string.
So your final solution will be something like:
@echo off
setlocal enabledelayedexpansion
set /p "mydate=Enter Date (format dd-mm-yyyy): "
for /f %%i in ('dir "C:\Users\xxx.xxx\Desktop\folder1\" /b /ad') do (
set "str=#%%i"
set "len=0"
for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!str:~%%a,1!" neq "" (
set /a "len+=%%a"
set "str=!str:~%%a!"
if !len! equ 6 if 1%%i equ +1%%i xcopy "C:\Users\xxx.xxx\Desktop\folder1\%%i\*.txt" "C:\Users\xxx.xxx\Documents\New folder" /D:!mydate!
)
)
)
Upvotes: 1
Reputation: 34979
Here is yet another method to achieve what you want (see all the explanatory rem
remarks):
@echo off
rem // Use a `for /D` loop to iterate through all immediate sub-directories in the given root directory:
for /D %%I in ("%UserProfile%\Desktop\folder1\*") do (
rem // Store path and name of currently iterated directory in variables:
set "DIRECTORY=%%~I" & set "NAME=%%~nxI"
rem // Toggle delayed expansion to be able to write and to read a variable within the same block of code:
setlocal EnableDelayedExpansion
rem // Check if directory name holds more than 5 characters:
if not "!NAME:~5!" == "" (
rem // Check if directory name holds not more than 6 characters:
if "!NAME:~0,6!" == "!NAME!" (
rem // The directory name is exactly 6 characters long.
rem // Check whether the directory name consists of decimal figures by (mis-)using a `for /F` loop:
set "FLAG=" & for /F "tokens=1 delims=0123456789 eol=0" %%J in ("!NAME!") do set "FLAG=#"
rem // The flag variable has not been set, hence the directory name consists of decimal figures:
if not defined FLAG (
rem // Do the actual copy job at this point:
xcopy /I /Y /D:09-09-2019 "!DIRECTORY!\*.txt" "!UserProfile!\Documents\New Folder"
)
)
)
endlocal
)
You were trying to use wildcards not only in the last element of a path, which cannot be done (in Windows), but you can use a for /D
loop to resolve the wildcards in upper directory levels, as demonstrated in the script.
The script uses ~
-modifiers (which are the same for for
meta-variables like %%I
and for argument references like %1
) to get the pure name of the currently iterated directory: %%~nxI
.
To determine whether or not the directory name is exactly six (6) characters long, sub-string expansion is applied.
To determine whether or not the directory name consists of decimal digits only, a for /F
loop is (mis-)used: for /F
splits strings into parts at given delimiter characters (option delims
); since all decimal digits are defined as delimiters, a directory named 1a2b3c
would be split into the parts a
, b
and c
(a
becomes assigned to %%J
then due to tokens=1
, the other parts become dismissed), but a directory name 123456
leaves nothing behind since this is a delimiter-only string, in which case the for /F
loop does not iterate at all. Together with a flag-like variable FLAG
that becomes set in the body of the for /F
loop we are able to determine whether or not the loop iterated, thus knowing whether the current directory name only consists of decimal digits.
The script writes to and reads from the variable NAME
in the same block of code, which can normally not be done, unless you enable delayed variable expansion.
You can use the system environment variable %UserProfile%
instead of specifying C:\Users\xxx.xxx
, so the script may even work on a system where the user profile directory is not at the default location.
Upvotes: 1
Reputation: 38708
You could use FindStr
to isolate the directories matching your pattern:
@Echo Off
Set "SrcDir=%UserProfile%\Desktop\folder1"
Set "DstDir=%UserProfile%\Desktop\New folder"
For /F Delims^=^ EOL^= %%A In ('
"Dir /B/AD "%SrcDir%\*" 2>NUL|FindStr "^[0-9][0-9][0-9][0-9][0-9][0-9]$""
')Do XCopy "%SrcDir%\%%A\*.txt" "%DstDir%\" /D:09-09-2019 /Y>NUL 2>&1
Just modify the paths between the =
and "
on lines 2
and 3
to suit your actual source and destination directories.
Upvotes: 1