Stefanski
Stefanski

Reputation: 13

Copy subfolders with specific (same) name to destination

Wrapping my head around following problem - also trying to illustrate what I try to achieve.

Source contains Subfolders named "import", which contain files and/or folders - (only) this "import"-folders should be copied to a destination directory with new individual names, as there can be only one folder with same name of course.

.Source
├── FolderA
│   └── import
│       └── Attachment
│   └── log
│
├── FolderB
│   └── import
│   └── log
│
├── FolderC
│   └── import
│       └── Attachment
│   └── log

.

.Destination
├── import27526
│   └── Attachment
│
├── import96385
│
├── import52987
│   └── Attachment

I tried to solve this in CMD with FOR and xcopy or robocopy, creating random destination-directories.

for /f "delims=" %%A in ('dir /a:d /b /s "import"') do (xcopy /y /i /S "%%A" "C:\temp\%%~nxA%random%")

Unfortunately it's not working, as all data from within various "import"-source folders is copied in a single destination directory instead of individual ones.

Any help is greatly appreciated!

Upvotes: 1

Views: 3874

Answers (3)

aschipfl
aschipfl

Reputation: 34909

Although user Compo's approach is probably the smartest solution, I want to provide a script that applies unique random numbers to the sub-directories import* in the destination directory:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_SOURCE=.\Source"
set "_TARGET=.\Destination"
set "_SUBDIR=import"

rem // Reset array variables:
for /F "delims==" %%E in ('2^> nul ^(set "$DIR[" ^& set "$RND["^)') do set "%%E="

rem // Build array of source sub-directories:
set /A "CNT=0"
for /D %%J in ("%_SOURCE%\*") do (
    for %%I in ("%%~J\%_SUBDIR%") do (
        set "ATTR=%%~aI" & set "ITEM=%%~fI"
        setlocal EnableDelayedExpansion
        if defined ATTR if "!ATTR:~,1!"=="d" (
            for /F "delims=" %%E in ("$DIR[!CNT!]=!ITEM!") do (
                endlocal & set "%%E"
            )
            set /A "CNT+=1"
        ) else endlocal
    )
)

rem // Build array of unique random numbers:
set /A "CNT-=1"
for /L %%R in (0,1,%CNT%) do (
    setlocal EnableDelayedExpansion
    set /A "RND=(!RANDOM!<<16)+(!RANDOM!<<2)+!RANDOM!%%2"
    for /F "delims=" %%E in ("$RND[!RND!_%%R]=%%R") do (
        endlocal & set "%%E"
    )
)

rem // Copy source sub-direcgtories to destination using random names:
setlocal EnableDelayedExpansion
set /A "CNT=0"
for /F "tokens=2 delims==" %%R in ('2^> nul set "$RND["') do (
    > nul xcopy /Y /E /I "!$DIR[%%R]!" "!_TARGET!\!_SUBDIR!!CNT!"
    set /A "CNT+=1"
    )
endlocal

endlocal
exit /B

If you are satisfied with sequential numbers, with respect to the order the file system returns the matching sub-directories (usually alphabetic in modern systems file like NTFS), you could use this script instead:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_SOURCE=.\Source"
set "_TARGET=.\Destination"
set "_SUBDIR=import"

rem // Build array of source sub-directories:
set /A "CNT=0"
for /D %%J in ("%_SOURCE%\*") do (
    for %%I in ("%%~J\%_SUBDIR%") do (
        set "ATTR=%%~aI" & set "ITEM=%%~fI"
        setlocal EnableDelayedExpansion
        if defined ATTR if "!ATTR:~,1!"=="d" (
            > nul xcopy /Y /E /I "!ITEM!" "!_TARGET!\!_SUBDIR!!CNT!"
            endlocal & set /A "CNT+=1"
        ) else endlocal
    )
)

endlocal
exit /B

Upvotes: 0

Compo
Compo

Reputation: 38613

Based upon my comment and your response, the following should work for you:

@For /D %%G In (".Source\*") Do @%__AppDir__%Robocopy.exe "%%G\import" ".Destination\%%~nxG_import">NUL

From :

For /D %G In (".Source\*") Do @%__AppDir__%Robocopy.exe "%G\import" ".Destination\%~nxG_import">NUL

Upvotes: 3

Salve
Salve

Reputation: 165

Below you have a simple code in Powershell that copies the folder with it's content and add a number to the folder in the destination. Was it something like that you were looking for?

Below script is a one-shot-deal and would fail if you run it twice (the number would start again at 1). You can simply ad a If-statement to check for used names if you want to run it multiple times.

$source = "SOURCE PATH"
$destination = "DESTINATION PATH"
$foldername = "FOLDERNAME"
$number = 0

$folders = Get-ChildItem -Path $source -Recurse | Where-Object {$_.Name -eq $foldername}
Foreach ($folder in $folders){
    $number++
    Copy-Item -Path $folder -Destination $destination -Recurse
    Rename-Item -Path "$destination\$foldername" -NewName "$foldername $Number"
}

Upvotes: 0

Related Questions