简体   繁体   中英

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 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 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!

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

eg 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 %%

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.

@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: http://www.jonasjohn.de/red.htm . 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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM