There is really no need to go through so much trouble.
With the exceptions of the PUSHD and POPD commands, the whole thing can be placed on one line like nephi12 did.
I'm puting everything on separate lines for clairity's sake, but will give two examples of it on one line later.
REM Set working directory
PUSHD C:\Episode\Footage\
REM Find all the sub directories of the working
REM directory, and if any exist execute the loop below:
For /d %%d in ( *.* ) do (
REM Move all files inside the subdirectory up one level.
move /s %%d\*.* %%d\..\.
REM Delete the directories if they are empty.
RD /y %%d
)
REM Return to your original working directory.
POPD
The above code pushes the current directory name into a stack, and changes dirs to Footage.
Then the For /d
command grabs all (if any) of the sub directories of Footage, and feeds them one at a time first into the MOVE
command, then into the Remove Directory command.
The MOVE /s
command moves all files in directory %%d (including any in sub folders) up one level.
Next the RD /y
command automatically deletes the now empty directories, or causes a soft error if they are not empty.
The final command returns the working directory to it's original location, POP
ing the path off the stack.
On one line, without the PUSHD
and POPD
commands and the directory cleanup, it looks like this:
Single Line Solution:
For /d %%d in ( *.* ) do move /s %%d\*.* %%d\..\.
Single Line Solution with Cleanup:
To include the cleanup just 'add' the and command &&
after the move
command and before the RD
, like so:
For /d %%d in ( *.* ) do ( move /s %%d\*.* %%d\..\. & RD /y %%d )
Why I did what I did.
The fastest way to move a whole bunch of files, is not to tell move
how and where to move each file, but to use wild cards that will allow Move
to figure out by it'self where to put them. So rather than tell it to move one file at a time, I give it wild cards, which allowsMOVE
to work at it's fastest. So I only feed it the individual source and destination directories, and say "copy ALL files from here to there".
A set of brackets (...)
can hold, what the interpreter considers a single line of code. Which causes a whole new set of problems, but it allows a special variable like %%d to exist on (what to us appears to be) multiple lines of code. I did that at the top. Later, I used another set of brackets to show the command interpreter what is part of a single line is inside a FOR
statement, and what is not.
I also used a bit of old DOS shorthand to specify a parent directory, ..
which allows me to not know the exact path of something, and still manipulate things in it's parent . As an example,C:\WINDOWS\..
is C:\
, and C:\WINDOWS\SYSTEM32\..
is C:\WINDOWS\
.
You might notice that I also used the file specification .
. That is probably unnecessary, but I've ran into enough trouble without it that I use it. It just makes clear to MOVE
that we are moving these files to a folder, not a file. And, oh yes, MOVE
will gladly move hundreds of your files on top of each other, ruining them all but the last one. You can imagine how I came to embrace the .
.
The &
allows you to string multiple commands, or programs, onto a single line of code, and allows me to tack the RD to the end of the line, and still have access to the special variables that the FOR
command created.
So, now if you were paying attention, you'd have realized that my second sentence was a fib. There is nothing stopping you from tacking a PUSHD &
and a & POPD
onto the beginning and end of that line.