Flatten Files in Subfolders on Windows 7 (cmd or PowerShell)

I have a large volume of files organized in a very hierarchical folder structure. In this structure, the file that I care about is always located in the lowest level of the folders. As such, I'd like to flatten the directory so that it's easier to access the files that I care about. However, I'd like to preserve the 2 higher levels (Person & Project) of the folder structure.

Here's an example of the EXISTING folder directory:

  • Directory
    • Tom
      • Project 1
        • Subfolder Level A
          • FileA
        • FileB
      • Project 2
        • Subfolder Level C
          • FileC
        • FileD
    • Jerry
      • Project 1
        • Subfolder Level E
          • FileE

Here's an example of the DESIRED folder directory:

  • Directory
    • Tom
      • Project 1
        • FileA
        • FileB
      • Project 2
        • FileC
        • FileD
    • Jerry
      • Project 1
        • FileE

I have tried doing something like this, however this flattens all of the files into a single directory:

for /r %f in (*) do @copy "%f" .

However, this produces:

  • Directory
    • FileA
    • FileB
    • FileC
    • FileD
    • FileE

I'd appreciate any guidance that you can offer. Thanks a lot!

4 Answers

Here is a Powershell approach. It gets a list of the folders at the level that you want. Then it moves all the sub files up to that level. it will also remove the sub folders.

$Rootfolder = Dir directory\*\* -Directory
ForEach($folder in $Rootfolder)
{ Dir $folder.fullname -Recurse -File | Copy-Item -Destination $folder.fullname Dir $folder.fullname -Recurse -Directory | Remove-Item -Force -Recurse -WhatIf
}

If you want it to delete, remove the -WhatIf from the last line.

Throw a couple of extra for loops around the one that works then.

e.g. First change to the name folder, then the project folder, looping through both levels.

for /D %n in (*) do ( pushd %n for /D %p in (*) do ( pushd %p for /r %f in (*) do @copy "%f" . popd ) popd
)

If you put this in a bat file, remember to replace % with %%

7
@echo off
pushd yourDirectory
for /d %%A in (*) do for /d %%B in ("%%A\*") do for /d %%C in ("%%B\*") do ( pushd "%%C" for /r %%F in (*) do move /y "%%F" "%%B" >nul popd rd /q /s "%%C"
)
popd

%%A contains something like "yourDirectory\Tom"
%%B contains something like "yourDirectory\Tom\Project 1"
%%C contains something like "yourDirectory\Tom\Project 1\subdirectory1" %%F contains a file to move, to any depth

At first I thought I could eliminate PUSHD/POPD and use

for /r "%%C" %%F in (*) do ... THIS DOES NOT WORK

But that doesn't work - the value after /R cannot use a FOR variable or delayed expansion because of how the command is parsed.

I tweaked @ScottC's answer and used the following code:

for /D %%n in (*) do ( pushd %%n for /D %%p in (*) do ( pushd %%p for /r %%f in (*.ppt) do ( move "%%f" "[ROOT_PATH_THAT_I_WANT]\%%n\%%p". ) popd ) popd
)

I ran this solution as a .bat file, which is why I used %% instead of %.

%%n = name (aka C:\Directory\Name)
%%p = project (aka C:\Directory\Name\Project)
%%f = file to be moved (recursively drilling through the folders and moving them up to the project level)

Ultimately, I wasn't able to get @dbenham's suggestion of deleting the empty folders to work, so I ended up using this utility: . So far it seems pretty intuitive and like it's taking care of the problem without much effort from me :)

Thanks for the help everybody!

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like