9

I have a small issue. I'm not super fluent in batch scripting but i'm trying to get better. I'm trying to get a script working at my current job that we can use to move all files in the last sub-directory of a parent up one directory.

The need is for moving image sequences delivered with a superfluous sub-directory up one sub-directory for effects workflow

essentially i'm being delivered 100s of image sequences as:

Episode/Footage/shot/resolution/shot.0000001.dpx

I would love a batch script i could move into the "Footage" folder that would parse the shot directories below them and move the image sequences out of the resolution folder and place them directly into the shot folder so the structure would look more like this:

Episode/Footage/shot/shot.0000001.dpx

This batch would need to be reused over many instances and just be robust enough to be reusable regardless of what the extensions on the image sequences are or the naming structure of the subfolders are.

tshepang
  • 12,111
  • 21
  • 91
  • 136
user2836139
  • 93
  • 1
  • 1
  • 3

3 Answers3

5
for /f "delims==" %%i in ('dir /a:d /b') do for /f "delims==" %%f in ('dir "%%i" /a:d /b') do (move "%%i\%%f\*" "%%i"&&rd "%%i\%%f" /s /q)


The * can be replaced with * . * (no spaces) to only grab files.
Use % instead of %% for use on the command line.
This will grab from any dir under Footage. Delete the first for loop and replace all occuences of %%i with shot to only grab from there.

Scott Ray
  • 11
  • 3
cure
  • 2,588
  • 1
  • 17
  • 25
  • This worked perfect! Thanks a bunch. Is there anything you could add to delete the sub-directory that you pulled it from? I really don't need the superfluous resolution directory there. – user2836139 Oct 01 '13 at 22:12
  • The revised answer doesn't seem to be any different in it's use then the original ... it's still leaving the folder it pulled the files out of there afterwards – user2836139 Oct 01 '13 at 22:45
  • Awesome! thank you so much ... now to pour over that impressive line of commands and decipher exactly what it is you're doing! – user2836139 Oct 01 '13 at 22:49
  • thank you for being so constructive. I am thirteen and that helps me want to continue learning. ;) – cure Oct 01 '13 at 22:54
  • UIAM that code doesn't move `the last sub-directory of a parent up one directory` but moves a fixed depth folder up one directory. If the OP is happy with that then that's ok. – foxidrive Oct 01 '13 at 23:42
  • 1
    It works perfectly with the directory structure that the OP asked for and showed. – cure Oct 02 '13 at 02:39
2
#!/bin/bash
mv Episode/Footage/Shot/*/* Episode/Footage/Shot

Or for more Fanciness:

#!/bin/bash
echo "Write the file path:" 
read file_path

mv $file_path/*/* $file_path/

This will ask you what the path is (This is Episodes/Footage/shot in your example) then find all the files in that path and all the files inside them and put them all in the path. You could also modify this if instead of putting the files in the path you want them in a different place you could add:

echo "Write the destination file path:"
read file_path2

in between: read file_path and mv ... and change:

mv $file_path/*/* $file_path

to:

mv $file_path/*/* $file_path2
Cnorwood7641
  • 336
  • 1
  • 5
  • 17
  • I guess this solution works in [tag:bash], while this question is tagged [tag:batch-file]? –  May 29 '17 at 09:35
  • 1
    This was four years ago and I don't even remember writing that. I guess I wasn't paying attention. – Cnorwood7641 May 29 '17 at 09:57
  • It's ok. It's very rare that the OP would reply to somebody after the answer is post for 4 yrs –  May 29 '17 at 09:58
0

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, POPing 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.

James K
  • 4,005
  • 4
  • 20
  • 28