So I have this script that takes files (.txtS for example), makes a folder of the same name for each one and moves 'em inside, each to the corresponding folder.
#echo off
for %%i in (*) do (
if not "%%~ni" == "organize" (
md "%%~ni" && move "%%~i" "%%~ni"
)
)
What I'd like to change is for the script to do the same thing but with Folders. So, take folder "1", create another folder "1" and move the first one inside. Willing to compromise on the name a little due to expected "this folder name is already taken" behavior.
I tried looking through Microsoft's documentation, but there are almost no matches for a newb like me to get an understanding of what's going on in the script (it was taken from another resource)
Related
I have 3 folders relevant to this script.
Folder 1 - contains all existing images (PNG), sorted into subdirectories ONLY, totalling thousands of individual files. None exist in the root folder.
Folder 2 - newly obtained images all in the root folder. I don't feel it's important to explain how they are obtained, as opposed to the fact that there will be a mix of duplicate files and new files.
Folder 3 - empty folder.
Due to folder 1 having the most files, I need to run a check of all the files in folder 2 to everything in folder 1 recursively, (and not the other way around, for performance reasons) then copy/move whatever is new to folder 3 (this way I can manually sift through and sort them accordingly).
Comparison can be done purely based on file name.
I've looked around forums extensively and found only 1 script that works the best, but relies on both folders having no subdirectories.
My problem is that I can't seem to get it to compare files to folder 1 recursively. It ends up just copying everything in folder 2 to folder 3, because it's checking against the root folder of folder 1, which contains nothing but subdirectories.
Code in question:
#echo off
set "Folder1=Folder1"
set "Folder2=Folder2"
set "Folder3=Folder3"
for /f "delims=" %%F in ('dir /b "%folder2%"') do (
if not exist "%folder1%\%%F" copy "%folder2%\%%F" "%folder3%" && echo Copied "%%F"
)
pause
Exit
Behaviour of above code:
Loops through every file in folder 2, and if a file with the same name doesn't exist within folder 1 (root folder only), it will copy it to folder 3.
I'd like it to check folder 1 contents recursively, not just the root folder.
I've tried tweaking it in many ways, such as changing the IN to NOT IN, or trying to find something to make the "%folder1%\%%F" have a recursive parameter such as "%folder1%\..\%%F" but nothing has worked with my limited knowledge.
Preferrably I'd like the whole process to be done with only 1 script.
Thanks in advance for your help. Please let me know if further clarification on anything is needed.
if [not] exist works only if you give it the whole path (which you can't, because you don't know, were it might be). So this approach doesn't help you.
Instead you could do a dir /s /b "%folder1%\%%F" || copy ...., but that means, you have to do a recursive dir for each file in folder2 - that's not what I would call performance.
Better generate a text file with the files in folder1 and use that as reference. (%%~nxA lists only name and extension of the files):
#echo off
set "Folder1=Folder1"
set "Folder2=Folder2"
set "Folder3=Folder3"
>Folder1Files.txt (for /r "%folder1%" %%A in (*) do echo %%~nxA)
for %%F in ("%folder2%\*") do (
findstr /x "%%~nxF" Folder1Files.txt >nul || copy "%%F" "%folder3%\" && echo Copied "%%F"
)
pause
Exit /b
(judging by your workflow description, consider move instead of copy)
I have read a couple of questions with a similar theme but none seem to cover this scenario.
I am looking to use a batch file that will check whether a directory is empty and if it contains files, move them to a corresponding folder. From here it will then check a second directory and do the same but to a different corresponding folder.
For Example:
Checks whether C:\One contains files, if it does move all the contents to C:\Receive\One
At this point (or if C:\One is empty) it will move and check whether C:\Two contains files. If it does it will move all files to C:\Receive\Two and stop the script. If C:\Two is empty the script will also stop here.
At present I'm using two scripts so was just interested as to whether there was a way to do it tidier with one script.
#echo off
for /F %%i in ('dir /b "c:\one\*.*"') do (
move C:\One\* C:\Receive\One
goto :EOF
)
echo No Files To Move
It looks to me like a simple move, in two lines:
move C:\One\*.* C:\Receive\One\
move C:\Two\*.* C:\Receive\Two\
Or, if you really need to do it in a batch-loop:
for %%a in (One Two) do (
move C:\%%a\*.* C:\Receive\%%a\
if ERRORLEVEL 1 echo No files to move from %%a
)
Need help with searching all sub folders. The current script works fine but only in the top directory. Any help?
md "C:\users\%username%\desktop\People"
SET LOGFILE=C:\users\%username%\desktop\movelog.txt
for /f "delims=" %%i in (people.txt) do (
move "%%i" C:\users\%username%\desktop\People >nul 2>&1
if errorlevel 1 (
echo %%i : Move failed >> %LOGFILE%%
) else (
echo %%i : Move successful >> %LOGFILE%
)
)
Assuming that im reading your question correctly, you want to be able to use the script from any location to find a folder thats specified within your text file to be moved to the new location correct? On linux machines a simple find * "foldername"|grep "foldername" would present usable code to find the files your looking for. Windows does have something similar but not nearly as easy as the linux version.
You can use the following code dir \ /A:D /B /S /O:G|find "%%i" to search for the folder recursively. However the code will output ALL instances of the particular string thats passed to it, which includes the file path for EVERYTHING thats in the particular folders contents. What you would be asking is to move all folders under that name to the new location.
Because of this, there needs to be some sort of identifier in each users folder as so to let the sorting program know that this is what im looking for and nothing else. If i had a blank text file labeled marker.txt in all the particular folders, i can run the code as dir \ /B /S|find "%%i\marker.txt" and this provides a unique marker for the searching program to identify with. This can be stored and sorted later into a variable so for example i had a marker.txt I can then run a simple set path=dir \ /B /S|find "%%i\marker", and make the new movement variable as move %path%\... So unless you have a file that is commonly shared by all of these, you may find it difficult to sort them.
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.
I'm new to the board so please go easy! :)
Basically, I'm writing a batch file to delete folders that don't have a file with a certain extension type in them.
so for example if i have the following folder
C:\MUSIC\FLAC\JAZZ\Jazzysong.ape
I need a bit of code that can delete the folder JAZZ because .ape is the wrong file type for the FLAC folder.
Any help would be awesome guys as I've tried variants of findstr, exist and writing to text file and trying to read the path using dir /s /b
I'm lost
I'm still unsure as to which kind of test you want to perform on a directory before deciding to remove it – "whether a certain file type exists" or "whether a certain file type doesn't exist". Your post seems to suggests it is the latter, so it must be the title that is misleading. For the purpose of this answer, I'm assuming that it is indeed the "whether a certain file type doesn't exist" test that you want.
Here's a very simplistic and unassuming approach to the problem:
#ECHO OFF
FOR /D /R "D:\directory_with_flac_files_only" %%D IN (*) DO (
IF NOT EXIST "%%D\*.flac" ECHO RD /S /Q "%%D"
)
That is, just traverse the directory tree and, for every subdirectory, check if it doesn't contain the necessary files. If it doesn't, say goodbye to it. (For safety, I added ECHO before the RD command, so that it does indeed say its goodbye but does not perform the real action, just in case you rush into executing the script without reading further.)
That approach is wrong, however. Even though a directory may not contain the required files, its sub-directories might, and this script does not verify that fact. As a consequence, you might lose some of your invaluable FLAC files. (And I've just saved you the grief.)
So, something more elaborate is needed here. The method I came up with consists in the following steps:
Sort the directories into two categories: those that contain the files with the necessary extension and those that don't.
Process the list of directories that do not contain the files:
1) if a directory is found in the other list, omit it;
2) if it is not found in the other list, remove it.
(In case you are wondering: a directory from the first list may indeed be found in the second list as part of its subdirectory's path.)
I'm far from being convinced that it's the best approach possible, but at least it should work (it did work for me, anyway). Here's my implementation of it:
#ECHO OFF
:: set the params
SET "ext=flac"
SET "rootdir=D:\dir_with_flac_files_only"
SET "todelete=%TEMP%\dirs_to_delete.txt"
SET "topreserve=%TEMP%\dirs_to_preserve.txt"
:: clear the temp lists
TYPE NUL >"%todelete%"
TYPE NUL >"%topreserve%"
:: sort the dirs
FOR /D /R "%rootdir%" %%D IN (*) DO (
IF EXIST "%%D\*.%ext%" (
ECHO %%D>>"%topreserve%"
) ELSE (
ECHO %%D>>"%todelete%"
)
)
:: process the sorted lists
FOR /F "usebackq delims=" %%D IN ("%todelete%") DO (
FIND "%%D" <"%topreserve%" >NUL || ECHO RD /S /Q "%%D" 2>NUL
)
You can still see the ECHO before RD, but consider it just my way of saying, ‘In case I missed something…’. Run the script and look at the output. If it correctly shows only the directories that are due to be deleted, remove ECHO and run the script again to get on with the action.