Command Line Fun: How to Flatten a Folder Hierarchy
January 25, 2011 30 Comments
Updated March 7, 2012: A reader pointed out that the command line solution presented here only works if all files in the folder hierarchy have unique names. Please see the comments to this post for two ways to work around this limitation.
Once upon a time, I knew most every command line operation that was available on a computer running Windows. Back in the day I even held a Microsoft Certified Professional title for MS-DOS. However, as time went by and Windows matured, I paid less and less attention to the command line and the enhancements that were made to it.
Recently I was asked if I knew how to “flatten” a folder hierarchy. That is, copy all of the files contained within a folder tree to the root of the tree (or to any single folder). Off the top of my head I didn’t know how to achieve this, but assumed that there was a utility app out there that would do the trick.
Well, I did find a way to do it, and lo-and-behold, no utility app is needed. Instead, all you need is the good old command prompt. I found this post on StackOverlow that shows how to flatten a folder hierarchy:
I’ve successfully tested the solution described there on both Windows XP and Windows 7.
Basic Command (the details)
I set up a hierarchy of folders with a few files at various levels of the hierarchy. The folder hierarchy looked something like this:
Then, at a command prompt I navigated to the root of the hierarchy (Folder0). From there, I ran the command…
for /r %f in (*) do @copy "%f" .
… which copied all of the files scattered throughout the hierarchy to the root (Folder0). (Note that the trailing period in the command is significant… it designates the current folder as the destination for the copy operation.)
The contents of the root folder of my folder hierarchy now looked like this:
So how does this work? If you type “for /?” at a command prompt, you find quite extensive information about the “FOR” command. To understand the specific command I used to flatten the hierarchy, this is the key information about the FOR command:
Runs a specified command for each file in a set of files.
FOR %variable IN (set) DO command [command-parameters]
%variable Specifies a single letter replaceable parameter.
(set) Specifies a set of one or more files. Wildcards may be used.
command Specifies the command to carry out for each file.
Specifies parameters or switches for the specified command.
And this is also relevant:
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
Walks the directory tree rooted at [drive:]path, executing the FOR
statement in each directory of the tree. If no directory
specification is specified after /R then the current directory is
assumed. If set is just a single period (.) character then it
will just enumerate the directory tree.
So in other words,
for /r %f in (*) do @copy "%f" .
means to start at the current folder and walk the folder tree (/r), and for every (*) file (%f) found, copy the file to the current folder (@copy ‘%f’ .).
Specify a Source and Destination Folder
A start folder and a destination folder can also be specified. To try this out, I created an additional folder named DestFolder at the same level as Folder0. With those folders in place, I executed the following command to copy all of the files in the Folder0 hierarchy into DestFolder:
for /r C:\Folder0 %f in (*) do @copy "%f" C:\DestFolder
Notice that this time a source folder (C:\Folder0) and a different destination folder (C:\DestFolder) were included in the command that was executed.
Move Instead of Copy
Finally, copying the files is useful, but sometimes the better operation is to move the files, rather than preserving the original files in their original locations. The Windows command prompt provides a command for moving files (MOVE), and it can be used in place of the “COPY” command used in the earlier examples.
The following command will move all of the files from the Folder0 hierarchy into DestFolder:
for /r C:\Folder0 %f in (*) do @move "%f" C:\DestFolder
There you have it. Simple, fast, and requires nothing more than a command prompt. Wonder what other command line goodies I’ve been ignoring?