Windows – Move all files and directories to new subdirectory in Windows

batch filecommand linewindows

I am reorganizing existing data, and I need create a new sub-directory to receive all existing files and directories. The purpose of this is to make room for a new product line, while at the same time improving the naming convention of existing data.

For example, data that currently looks something like this:

\root directory\
+-proj1357
  +-closing binder
  +-refi
  +-compliance
+-proj2468
  +-disbursements
  +-compliance
+-proj3579
  +-pre-close
  +-compliance

Should actually look like this:

\root directory\
+-proj1357
  +-dpl
    +-closing binder
    +-refi
    +-compliance
+-proj2468
  +-dpl
    +-disbursements
    +-compliance
+-proj3579
  +-dpl
    +-pre-close
    +-compliance

The problem I am having is that I can't seem to get the right command without getting stuck in a recursive loop. While hacking this together, I frequently ran into the error, "cannot perform a cyclic copy".

The good news is that I've got a working solution, but it requires three separate commands, and custom syntax for each project directory.

command 1> ROBOCOPY G:\proj1357 DPL /E /MOVE
command 2> MOVE G:\proj1357\DPL\DPL\*.* G:\proj1357\DPL
command 3> RMDIR G:\proj1357\DPL\DPL\

As far as I can tell, command 1 moves all files and directories into the new sub-directory. It also causes a recursive problem by moving files in the project-level directory into a deeper sub-directory. So I rely on Command 2 to recover files that were once in the project-level directory. Then Command 3 removes the deeper sub-directory.

Is there a better way I can run a command or batch file through a Windows-based system? Ideally it would crawl through all the project-level directories, and move the contents to the new sub-directory. I'm looking at processing over a thousand projects, so I think it is worth the time figuring out how to loop it correctly.

For more visual context of what I'm up against, see screenshot below.
screenshot of Windows directory


UPDATED

After trying to make it work using the three-step command line method outlined above, I gave in and adapted jiggunjer's answer to fit my environment. Below is the MS batch file that I used. I've also added remarks to clarify the purpose of each line.

@echo off
rem run this batch file in top level directory
rem top level directory should contain all project number directories
rem assumes that all directories starting with a digit are project number directories 

rem initialize the listing of all directories
set rootlist=dir /b /a:D

rem initialize numerical filtering
set filter=findstr "^[1-9]"

rem loop through all directories that comply with filtering (start with a digit)
rem use command extension /F to process (in this case) command output
rem identifies all project number parent-directories
rem assign parent-directories to variable %%P, as in 'Project'
FOR /F %%P in ('%rootlist% ^| %filter%') DO (
    rem pass the variable %%P to the moveproject loop
    call :moveproject "%%P"
    
    rem move files that were ignored by the robocopy command
    rem these are 'loose' files that were in the project number directory, but not saved in any subdirectory
    rem assumes the robocopy command successfully creates the DPL directory
    MOVE %%P\*.* %%P\DPL\
)

rem pause to review command log
pause

:moveproject
rem ensure that the parameter has value
rem converts variable %%P to parameter no. 1
if not [%1] == [] (

rem loop through all sub-directories under each project number
rem use command extension /D to process directories only
rem removing any surrounding quotes (") from parameter no. 1 by using optional syntax -- percent-tilde
rem assign sub-directories to variable %%O, as in 'Origin'
FOR /D %%O IN ("%~1\*") DO (
    rem display values
    echo project number %%P
    echo directory origin %%O

    rem delimit origin directory using backslash character
    rem use command extension /F to process (in this case) strings
    rem assign the second delimited piece to variable %%D, as in 'Destination'
    rem effectively drops all text to the left of the first backslash character
    FOR /F "tokens=2 delims=\" %%D IN ("%%O") DO (
        rem display values
        echo %%D
        echo directory destination %%P\DPL\%%D
        
        rem move all directories to DPL sub-directory
        rem simultaniously creates the receiving DPL directory
        robocopy /E /MOVE "%%O" "%%P\DPL\%%D"
        )
    )
)

Best Answer

In each of those 8 root directories run this command:

FOR /D %p IN ("*") DO robocopy /E /MOVE "%p" "%p/DPL"

Powershell 3.0+ version:

gci -dir -name | foreach-object{robocopy /E /MOVE $_ ($_ + '\DPL')}

OR

Based on your screenshot an all-in-one solution would be something like:

@echo off
REM Assume: Running in top level dir. 
REM Assume: Only project parent fodlers start with a digit.
set rootlist=dir /b /a:D
set filter=findstr "^[1-9]"
FOR /f %%d in ('%rootlist% ^| %filter%') DO (
call :moveproject "%%d"
)

:moveproject
if not [%1] == [] (
FOR /D %%p IN ("%~1\*") DO robocopy /E /MOVE "%%p" "%%p/DPL"
)

Happy re-parenting!

Related Question