Command Promp to copy ONLY images from FOLDERS and SUBFOLDERS - batch-file

I'm wondering if it is possible to set up a batch command to perform this action.
Once .bat file is executed, ALL images from folders and sub-folders would be copied to my location on the desktop.
Example:
Original folder is located:
\intranet\file_location\PP Complete Images (in this folder will be loads of other folders and in those folders there will be .jpg images)
Destination file would be based on the desktop.
So I need to extract .jpg images from all folders and sub-folders.
If image already exists in original folder, skip the image or overwrite as script will be executed every morning.
Or should I look for a software to do this for me?
Existing code:
cd c:
cd\
copy "\\intranet\PP Complete Images\Master Image Folder*.jpg" "C:\Users\username\Desktop\Master Image Folder"
copy "\\intranet\PP Complete Images*.jpg"
exit

How do you want it?
It isn't quite clear to me, how the result exactly should be -- should it be flattened or should it be hierarchical as well?
Look at this for example:
source
folder-1
folder-1-1
image1.jpg
folder-1-2
image2.jpg
cheese.jpg
image3.jpg
some_text.txt
folder-2
folder-2-1
image3.jpg
some_music.mp3
cheese.jpg
target
Should the result be basically a copy of the shown hierarchy (without any other file than the jpgs), or should it be a flattened result like this one:
source
... (see above)
target
image1.jpg
image2.jpg
cheese.jpg
image3.jpg
image3.jpg
How can you do it?
Flattened
You can use DOS' for command to walk directories1 and make a custom function2 to handle the files:
#ECHO OFF
for /r %%f in (*.jpg) do call:copyFile %%f
GOTO END
:copyFile
copy /V /-Y %~1 ..\target
GOTO:EOF
:END
Meaning: for every %%f in the listing of *.jpg from the current working dir, execute function copyFile. The /r switch makes the listing recursing (walk through all subdirectories).
In the function, the argument passed to it (now known as %~1) is passed to the copy function: Copy the file to the target directory which is ..\target in this case. /V lets copy verify the result, /-Y lets it ask for permission to overwrite files. See copy /?!
Very big problem: If you have one or more files in different subfolders of your source directory, which have the same name (like the two cheese.jpgs in my example), you will loose data!
So, I wouldn't recommend this approach, as you risk loosing data (digital cameras are not very creative in naming pictures!).
Hierarchical
Just use robocopy:
robocopy /S <sourcedir> <targetdir> *.jpg
/S creates and copys subfolders as well. You can also use /DCOPY:T to make the directories have the same timestamp than the original ones or /L to preview the actions of robocopy.
Small problem: The /E switch handles subfolders as well, even if they are empty. /S handles subfolders as well, but not, if they are empty. But it handles them, if they are not empty, but have no JPG inside -- so, subfolders without JPGs will result in empty folders in the target folder.
Robocopy has loads of parameters, so check out robocopy /?.
Hope this helps! :-)
1Found here: How to traverse folder tree/subtrees in a windows batch file?
2Found here: http://www.dostips.com/DtTutoFunctions.php

Your existing code:
the cd c: is incorrect. To switch the current drive to c: use
c:
The cd \ is redundant. Your remaining code specifies the directories, so the current directory is irrelevant.
Your first copy command has three problems. Master Image Folder*.jpg means all filenames beginning Master Image Folder and ending .jpg. You probably meant Master Image Folder\*.jpg meaning all files ending .jpg in ...\Master Image Folder\
C:\Users\username\Deskto... is probably an error. It is a literal path, so the actual directory would be C:\Users\username\Deskto... You would probably need C:\Users\%username%\Deskto... to substitute-in the current username.
And then the job would stop on a filename-match, so either you'd be pressing A to overwrite all or you'd be pressing y or n for each name-match.
Your final copy command has no specified destination directory.
You can edit-in your actual code by using the edit button under the original text window, cutting-and-pasting your actual code - censoring if necessary, selecting the resultant code block and pressing the {} button above the edit box which indents each line with the effect of formatting and hilighting the code.
The simplest solution is probably to use
xcopy /d /y /s "\\intranet\PP Complete Images\Master Image Folder\*.jpg" "C:\Users\%username%\Desktop\Master Image Folder\"
which will copy updated files (/d) with automatic overwrite (/y) and scanning subdirectories (/s) from-name/mask to-directory.
This would create an identical directory-hierarchy to the original subtree under the destop's Master Image Folder directory.
You could extend this to
for %%a in (
"\\intranet\PP Complete Images\Master Image Folder"
"\\intranet\wherever\somewhere"
) do xcopy /d /y /s "%~a\*.jpg" "C:\Users\%username%\Desktop\Master Image Folder\"
to perform the same action on multiple directory-subtrees; but you need to ensure that the destination directory is not within any subtree selected for inclusion in the list within the parentheses.
I'd advise against "flattening" the output because if you do that, the latest whatever.jpg from each of the subtrees will end up in your destination directory, without notification that there are many possibly different whatever.jpg versions.

I do believe the solution to your problem would be Robocopy.
Robocopy is just plain awesome!
Here is the syntax of robocopy-
robocopy [Source] [Destination] [File] [...] [options]
Source
Specifies the source folder. Where you want to take the files from.
Destination
Destination directory/folder.
File
Here we are! This is what will help you. Here you can specify an extension you want to move. So in your case, your code would look somewhat like this.
robocopy *.jpg c:\destinationdir /S /MAX:1048576
*To execute this .bat every morning go to a program called task scheduler, dont worry, its built into windows. http://windows.microsoft.com/en-US/windows/schedule-task#1TC=windows-7
*Then Click on Create basic task, and set your task to whenever you like!

Thanks guys for your help!!!
I got it solved and there is a code below if someone would ever need something similar:
pushd Z:\intranet\PP Complete Images\
for /r %%a in (*.jpg) do (
XCOPY /Y "%%a" "C:\Users\username\Desktop\Master Image Folder"
)
popd

Related

Replace file.old with file.new in multiple subfolders

I am trying to replace over 400 audio files, in just about as many sub-folders, with a updated format required by the program. It's the same file in each location but its how they require it for their xml file. I found several similar post, replacing files in multiple sub-directories like this one Replacing a file into multiple folders/subdirectories this I assumed would meet my needs.
I want to find all AR33.mp3 files in SFX'x folders, and replace with the new required AR33.wem my issue is as follows:
FOR /R C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\GoldenEye\SFX %%I IN (AR33.mp3) DO echo COPY /Y C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\sfxwems\AR33.wem %%~fI
This does the reverse and copies the file I want to overwrite, ar33.mp3, all over the folder structure in every folder where there shouldn't be any. but it does say 1 file copied after each entry.
(AR33) creates extension-less copies. adding (*AR33.mp3) does nothing, same with (*AR33.mp3 *) does nothing, even with "1 item copied" pointed out in the console. At this point I'm trying what I can to get this to work randomly doing stuff. Changing COPY to replace give a invalid switch -/y. Am I using the wrong "script" to do what I want? Because even changing one of the AR33.mp3 over to a .wem didn't see any change after replacing the line .mp3 to .wem. I assume I need to fix what its searching for and what its copying.
Updated bat:
FOR /R "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\GoldenEye\SFX\" %%I IN (AR33.mp3) DO echo COPY /Y "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\sfxwems\AR33.wem" "%%~fI"
Output sample:
C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted>echo COPY /Y "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\sfxwems\AR33.wem" "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\GoldenEye\SFX\AAC0\ShipName__PASC045\isPlayer__False\AR33.mp3"
COPY /Y "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\sfxwems\AR33.wem" "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\GoldenEye\SFX\AAC0\ShipName__PASC045\isPlayer__False\AR33.mp3"
You want to replace .mp3 with .wem as well. For now you are simply copying the .wem file and naming it with a .mp3 extension. So we could just rename the .mp3, then copy the .wem file to it.:
#echo off
for /R "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\GoldenEye\SFX\" %%I in (*AR33.mp3) do (
echo ren "%%~fI" "%%~nI.wem"
echo copy /Y "C:\Users\trevo\Desktop\ProjectGoldenEYE\811converted\sfxwems\AR33.wem" "%%~dpnI.wem"
)
Please take note before continuing. The above will only echho the result, once you are happy that it does what you want, then only remove `echo from both strings in the code block.
It is also always a good idea to backup files before running a big copy process like this.

How to delete files matching a certain pattern in their name?

I'm creating a batch file that deletes all Rar$DIa0.??? folders in the %TEMP% directory.
Is this possible, and how to do it?
The ??? is three randomized numbers. And that's where I have trouble with - deleting all folders that have Rar$DIa0. in the name.
for /d is designed for just this type of use. Something like this should work (remove one of the % if you're testing from the command line):
for /d %%i in ("%TEMP%\Rar$DIa0.???") do rd "%TEMP%\%%i"
The /d makes it work on directory names instead of file names.
If you want to make it easier on yourself, change to the %TEMP% folder first:
pushdir
cd /d %TEMP%
for /d %%i in ("Rar$DIa0.???") do rd "%%i"
The ??? makes it only act on folders that have three letters after a .. If your folders don't have just a three letter extension, change .??? to .*. If you've got a typo, and there is no actual . in the foldername, just remove it and use Rar$DIa0??? or Rar$DIa0*
You may want to test it first by changing rd to echo to make sure you get the folders you want before actually deleting them.
For more information about for (pun intended) type for /? from a command prompt.
The command line to use in a batch file for this task is:
#for /D %%I in ("%TEMP%\Rar$DIa0.*") do #rd /Q /S "%%I"
Command FOR with option /D searches in folder defined by environment variable TEMP for subfolders with folder name starting with Rar$DIa0. not having hidden or system attribute set.
The loop variable I holds for each found subfolder matching this folder pattern the name of found folder with full path without double quotes although the path to temp folder very often contains 1 or more spaces.
For that reason just the command RD with the parameters /Q for quiet execution and /S for deleting also all subfolders in the specified folder must be called with referencing the current value of loop variable I enclosed in double quotes.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
for /?
rd /?
By the way: WinRAR deletes the temporary folders usually automatically, except a file is opened from within an archive for viewing/modifying it in another application and WinRAR is closed before the other application is exited with the opened file. In this case WinRAR can't delete the temporary folder with temporarily extracted file because the file is still opened in another application. Of course also command RD can't delete the temporary folder if this folder is still the current directory of another application or a file in this folder is still opened by another application with a read/write access lock.

Batch file to rename images for WD Live TV

Apologies if this has been answered, the search gives something similar but not exactly what I'm after.
I use XBMC and a Western Digital TV Live as media centers. XBMC uses folder.jpg for movie box art. However, the WD uses both folder.jpg and moviename.jpg.
My folder structure is as follows:
Films\movie1\movie1.mkv(or avi etc...)
Films\movie1\folder.jpg
Films\movie2\movie2.mkv (etc...)
Films\movie2\folder.jpg
What I'm after is a .bat file that will scan the entire films directory, copy the folder.jpg and rename the new jpg using the name of the folder that folder.jpg is in. The original folder.jpg should remain.
Essentially from:
Films\movie1\folder.jpg
To:
Films\movie1\folder.jpg
and
Films\movie1\movie1.jpg
This should happen to each folder in Films.
I'm sure this must be possible but to be honest my knowledge of .bat files is very limited.
You can use a FOR /D loop to iterate over subdirectories of Films:
#ECHO OFF
FOR /D %%I IN ("D:\Path\to\Films\*") DO (
COPY "%%I\folder.jpg" "%%I\%%~nxI.jpg"
)
In the loop, the subdirectory's full path is referenced as %%I and its name alone as %%~nxI (could be just %%~nI if the name never includes a .).
You could run the loop directly from the command prompt, but you'd need to replace the double % characters with single %:
FOR /D %I IN ("D:\Path\to\Films\*") DO COPY "%I\folder.jpg" "%I\%~nxI.jpg"
Please note also that if a moviename.jpg already exists, the COPY command will stop for confirmation of overwriting the file. If you just want to overwrite it anyway without manual confirmation, add the /Y switch:
COPY /Y ...
for /d %%a in (*) do if exist "%%~a\folder.jpg" echo copy /b "%%~a\folder.jpg" "%%~a\%%~na.jpg"
Remove the echo to get it working.

batch Moving all files in 100s of folders up one folder

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.
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.
#!/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
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.

xcopy does not create directory structure

I have a strange problem with xcopy in Windows XP Professional. I don't know if its a stupid question as I am specifying only a file as the source, so should I even expect any other behavior ? This is it:
I am using xcopy <src> <dest> /s/y.
<src>=C:\sourcefolder\a\b\c\d\something.java and
<dest>=C:\destinationfolder.
Now xcopy copies the file but does not create the directory structure \a\b\c\d\ inside C:\destinationfolder .
what I want is C:\destinationfolder\a\b\c\d\something.java and
what I get is C:\destinationfolder\something.java
I have tried to run it in destination folder C:\destinationfolder by specifying a . for target folder
Tried it without any target in above
There is a script I have which calls xcopy iteratively so I am left with C:\destinationfolder\many java files without any directory structure.
A. Yes I have done xcopy /? to see all options
B. /T also does not create any empty directory structure
C. I can not go to source folder a\b\c\d\ and run xcopy . <dest>
UPDATE
I removed my previous answer on using ROBOCOPY. I believe the following will do what you want using XCOPY.
Assuming your folder structure is like this:
SOURCE = C:\MyJavaStuff\A\B\C\D\something.java
DEST = C:\MyDestination
Run XCOPY like this:
XCOPY C:\MyJavaStuff\something*.java C:\MyDestination /S /E
Note the * in something*.java.
The problem is that you are specifying which file to copy in the source. xcopy won't create the folder structure in this case. However, if you change your call to xcopy to
xcopy *.java C:\myfolder /s/y
it will copy the .java files and the folder structure as well. You need to specify a wildcard for this call to work as you want. If you want only to copy specific files, you will have to adjust the call to xopy, e.g.:
xcopy something.jav* C:\myfolder /s/y
Edit
You say that you get the list of files to copy from another command. If you can output this list of files in a text file, you could do the following:
FOR /F "tokens=* delims=," %F in (d:\test\list.txt) DO xcopy src\%~nxF* .\dest /S /Y
What this command does is read a text file ("d:\test\list.txt" in this case), read every line, and for each file, run xcopy, adding a wildcard at the end of the file name to make sure it creates the folder structure.
I'm assuming here that:
You can get the list of files in a text file, with only the file names (and optinally the paths)
You know the source folder ("C:\sourcefolder" in your example, the folder structure "a\b\c\d" does not need to be known) and can use it in the FOR command.
You can also use the following form:
FOR /F "tokens=* delims=," %F in ('cmd') DO xcopy src\%~nxF* .\dest /S /Y
where cmd needs to be replace with the command you use to generate your list of files to copy.
Note that if you use this FOR command in a batch file, you need to replace %F with %%F (and %~nxF* with %%~nxF*).
I had a look at the xcopy switches and you can copy the directory structure with /T, although that doesn't copy empty directories you can override this with /E. So your command would look like this:
xcopy C:\sourcefolder\a\b\c\d\something.java C:\destinationfolder /T /E /S /Y
Hope this helps!
In order to get C:\destinationfolder\a\b\c\d\something.java XCOPY needs to know how much of C:\sourcefolder\a\b\c\d\something.java to duplicate.
You can use:
C:
cd \sourcefolder
XCOPY something.java* C:\destinationfolder\ /S
Just be aware that this may have the side effect of also copying C:\sourcefolder\oops\something.java to C:\destinationfolder\oops\something.java as well as any other matches for something*.java under C:\sourcefolder\.
It seems to me that xcopy is typically used for copying directory trees, not single files (though it can work). And, xcopy will recreate the directory structure under the source folder in the target folder. If xcopy is given the /i switch, the target folder is assumed to be a directory. It will be created if it does not exist, even if there are multiple parents that need to be created.
You have C:\MyJavaStuff\A\B\C\D\something.java - that is your source. You want to end up with something.java not in C:\destinationfolder, but in C:\destinationfolder\A\B\C\D - so that is your target. You don't even have C:\destinationfolder. That is OK, with /i the entire path will be created.
xcopy /i c:\MyJavaStuff\A\B\C\D\something.java C:\destinationfolder\A\B\C\D
If something.java were the only file under C:\MyJavaStuff, you could also use
xcopy /sei c:\MyJavaStuff C:\destinationfolder
That would recreate the entire tree structure, copying your file. But if there are other files (and folders) under MyJavaStuff they would also be copied.
I have written a very similar batch file using xcopy. Perhaps what I did will help you.
This is the command I used:
xcopy "c:\Data Files\Dave's Data\*.*" "m:\Dave's Data" /R/D /E/H
In this case, Dave's Data on the source contains an entire directory tree containing at least 50,000 files & exceeding 75GB data. It runs perfectly on Windows XP
I found /T was unnecessary as the directory tree is copied. I also found /S was unnecessary as /E copied directories & sub-directories including empty ones. I included /R to copy & overwrite read only files on the destination. /H copied hidden directories. /D copied only newer files. I use this as a daily backup tool for my data.
The only problem I have is while this command will work on Windows 7 the first time, it will not work on subsequent runs when the destination directory tree exists. I suspect this is due to a privilege issue as the xcopy command will work on subsequent runs on Windows 7 within a cmd.exe window.

Resources