Using batch script to compare contents of 2 folders recursively, and copy the difference to a third folder - batch-file

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)

Related

Setting up Source and Destdir in a batch

for /L %%f in (1,1,10) do copy File1.txt %%f.txt
this code does the job very well, but I'm trying to understand how to change it to make it read
subfolders, so that I don't have to keep moving the batch file to every folder
I saw this, but not really sure how to put it together
#echo off
SET "sourcedir=C:\Users\user\Desktop\Main\Original"
SET "destdir=C:\Users\user\Desktop\Main\Copied"
for /L %%f in ('dir /s 1,1,10) do copy *.txt %%f.txt
in the section - copy *.txt %%f - I put a * so that it can only look for .txt files, but this action
slows down the coping and then stops working.
I know my code is a mess, just trying to put something together
I have many Subfolders and each folder has 1 txt file in it with all random names
and I need to make multiple copies of each file.txt in each folder
I have so many subfolders that it would literally take me months of time to get all files copied
and by then I would have many more new files to work on
so getting this copier to read Subfolders is like top priority for me.
I would like help putting this together and then explaining how it links
because I'm interested in applying the Set and dir to other batch file I have
Please any details on this will be much appreciated
I was told to look into xcopy and robocopy, but I have no idea were to add a counter
#echo off
for /1 %f in (1,1,10) do xcopy "C:\Sources" "C:\Target" /c /d /i /y
exit
So I have this that reads from source and dumps in main folder where the batch is
Option 1)
for /L %%f in (1,1,10) do xcopy "C:\Source Address\*.txt" %%f.txt
Option 2)
for /L %%f in (1,1,10) do xcopy "C:\Source Address\" "C:\Destination Address\ %%f.txt"
The thing I don't like is that is asks me a question
and I have over 10,000 txt files, I can't sit here and press F for Filename
10,000 times, can we disable that
OK, so I got this working
all I need help with is were to add this /c /d /i /y
I am still trying to get it to read Subfolders with the batch sitting
in the main folder and me not having to move files back and forth
Option 3)
for /L %%f in (1,1,110) do copy "C:\Source Address\*.txt" %%f.txt`
This works well with the Source and the wild card #magoo told me to add
the Source before the .txt file
But with this code I would still have to open hundreds of folders and move
the file to the source run the copier and then move back all copied files
Still need help with Subfolders
for /L %%f in (1,1,10) do copy File1.txt %%f.txt
will vary %%f from 1 (the first number in the parenthesised list) to 10 (the last) in steps of 1 (the middle) and will therefore copy file1.txt to 10 separate files, 1.txt to 10.txt.
Since there are no paths specified, the copy will be performed from file1.txt in the current directory to 1.txt .. 10.txt in the current directory.
If you were to put your batch file in any directory that is mentioned in the path variable (just execute path at the prompt to show it) then no matter where the current directory is, you could just use that batch filename to execute the batch, and the files would be created by copying file1.txt in the now-current directory to 1.txt .. 10.txt in the now-current directory - if file1.txt exists in the now-current directory, and if not, it will generate error messages reporting that the source file is missing.
If you were to replace file1.txt in the batch with "x:\wherever\file1.txt" then the file would be copied specifically from the file "x:\wherever\file1.txt" regardless of whether file1.txt exists in the now-current directory. (And please get used to "quoting file or pathnames" as it will avoid a whole slough of problems when you tackle names containing spaces and some other special characters).
I have no idea how for /L %%f in ('dir /s 1,1,10) do is supposed to work since according to Hoyle, the first element in the parenthesised list should be a number. I'd suggest that we have a small transcription problem here.
Th slower and slower problem - yes, understandable. You are creating more and more .txt files, and copying all of them to a new destination...
Perhaps referring to This response and question might show how to solve your subdirectory-scan issue.

Batch Script Deleting Files Instead of Moving

I am still a beginner to batch scripting so I would appreciate more explanation than usual to help me if at all possible.
Purpose:
I wrote this script to try to move files based on whether they have a folder's name within their name. For example, I have a folder named "cow" and a file named "cow_5234.txt", the file would be moved into the folder. The purpose of this is to move files with company names to a company folder from a messy folder full of files so I don't think a file going to the wrong folder will be much of a problem.
Problem:
The problem I am having is that many of the files that are supposed to be transferred to folders are being misplaced. I have around 3000 files in a folder along with 300 folders and this script. After I run it, only around 100 files get placed into the correct folders, while 900 are left behind (because they don't have a folder name within them) while the rest just disappear.
What I have tried to do:
I have gone through and checked the original list of folder names, which is all correct. Then I modified the script to output the filename to a .txt file instead of move it. Instead of getting a reasonable amount of files, there are 4000 files (I checked the line count). Some of these files don't have a folder name in them. I then took a subset of around 200 files and 20 folders and ran the script with them. For some reason, only 80 files remained, 1 was placed into a folder, although it didn't have a single similar character as the folder, and the rest just disappeared. I'm not sure what is happening at all. Here is the code:
#echo off
dir /a:d /b > list.txt
for /F %%i in (list.txt) do call :process %%i
goto :eof
:process
set "search=%1"
for /f "eol=: delims=" %%F in ('dir /A:-D /b^|find "%search%"') do move /Y "%%F" "%search%"
goto :eof
Edit 1:
As recommended in the comments, I have added a "goto :eof" to the end of the block of code, however, the problem still remains.
Edit 2:
I didn't add a "goto :eof" to the end of the main function. Thanks for clarifying!

Combining Multiple Folders with prefix and timestamp in folder name into new folder with just prefix

So, this is a particularly puzzling problem for me. I'm open to using whatever I must, but I typically only write simple batch files.
I have a huge research project at the hospital where I work, and the data I'm working with is presented to me with a 4 digit subject identifier followed by a timestamp, as seen in this example:
6443_20170419_141200416
6443_20170419_141200447
6443_20170419_141200500
6476_20170419_141200537
6476_20170419_141201112
etc.
I have literally thousands of these folders, and in each of them is between 1 and 3 files with very long file names - the only commonality is the .DCM extension.
What I'd like to do is have a script that will extract the first 4 characters of the folder name, create a new directory with that 4 character name, and then copy any files located within folders with the matching prefix into the newly created folder.
For example, let's say the folders which all start with 6443 have several .DCM files in them. I want to create a new folder named 6443 (in a different location that the then current directory, to avoid accidental deletion), and then move all of the .DCM files from each directory into the new folder.
I have a .TXT file which contains all of the subject ID #'s that I've been using for various other scripted tasks, using FOR /F to walk this file, if that gives anyone an idea for a solution.
This once is really picklin' my noggin. Help!!!
----- ADDITIONAL INFO -----
I've been making progress, but it's still not right. I'm using the script as shown below, but it's moving ALL of the files in each of the folders to each of the newly created folders, instead of sorting them by 4 digit prefix.
#ECHO on
cls
FOR /f "delims=_" %%a IN ('dir /b /ad "*_*_*"') DO (
if not exist %%a MD .\combined\%%a
FOR /d /r %%d IN ("*") DO (
copy %%d\* .\combined\%%a\*
)
)
Here is the corrected script:
#echo on
cls
for /F "tokens=1* delims=_" %%a in ('dir /B /A:D "????_*"') do (
if not exist ".\combined\%%a\" md ".\combined\%%a"
copy ".\%%a_%%b\*.dcm" ".\combined\%%a"
)
What I changed:
the tokens option has been added to the outer for /F loop in order to be able to rebuild the original source directory name later;
the directory search pattern has been improved;
the if query checked the wrong directory;
the inner for loop has been removed, because it iterated over all source directories again;
the source and destination paths for the copy command have been adapted;
all paths are properly quoted;

Copy subfolders with exclusions

I have a messy situation on production server, there is a location on production which should only contain 3 folder however due to not following some process we have got more than 1000 folders and files and I am aiming to clean it via a batch file so that there is no chances of human error.
So I would like to copy all folders and files except 3 folders to a new location. can someone help in this as not able to put logic to exclude these 3 folders.
Create a file called ex.txt that includes 3 lines, each of which is the name of the folder that you would like to exclude from the copy, e.g.:
\folder1\
\folder2\
\folder3\
Now, go to the parent of the high-level directory (say, directory_to_copy), that you would like to copy, in which location exists the ex.txt file, and type
xcopy /e /i /exclude:ex.txt directory_to_copy destination_name
This will exclude the folders folder1, folder2, and folder3 from the copy.
Note: the backslashes \ are important to ensure that the other folders containing those strings (folder1, folder2, and folder3) are not excluded.
This writes tempmove.bat.txt in the same folder as the batch file that contains the move commands to move every folder except the three folders shown (testenv stageenv prodenv).
You can examine the text file before renaming it to .bat to actually use, if it shows the right commands.
Make sure "d:\wrong folders" folder already exists.
#echo off
cd /d "c:\production folder"
(
for /d %%a in (*) do (
if /i not "%%~nxa"=="testenv" if /i not "%%~nxa"=="stageenv" if /i not "%%~nxa"=="prodenv" echo move "%%~fa" "d:\wrong folders\%%~nxa"
)
)>"%~dp0\tempmove.bat.txt"
pause

Batch move files in folders to newly created folders

I want to move all files in some folders to a newly created folder in that same folder. For easier understanding, see the example below (the input is shown left, output is shown right):
C:\1\A\file1.tif C:\1\A\Named\file1.tif
file2.tif file2.tif
file3.tif ==> file3.tif
C:\1\B\file1.tif C:\1\B\Named\file1.tif
file2.tif file2.tif
file3.tif file3.tif
In the example above, I have only shown the first three files in every folder, but the total number may vary (usually there are 1000 files per folder). Also, I have only shown two folders (A and B), but the total number of folders may vary as well (usually about 10 folders). Finally, I have only shown the folder '1', but the number of these kind of folders may also vary (usually '1' through '10'). So I was looking to a script that could do these actions independent of the number of files or folders, and independent of the names of the folders/files (I chose '1', 'A' and 'file1.tif' only as examples).
The idea is that, now, I have to manually create empty folders (called 'Named' in the example above) in each folder ('A' and 'B' in the example above) where the files are. Then I have to manually move all the files into that newly created folder 'Named'. I have to do this for all folders (about 100). I can do this entire process manually if I had to do it only once, but the thing is that I have to do this process many times :-). So automating this would save a lot of time.
Does anyone know a script that can do this? Thanks a lot!
tested a little, this might work, in a command file
make a cmd file with these lines
for /r %%a in (*.*) do call :singlecopy %%a
goto :eof
:singlecopy
set src=%~p1
set dst=%~p1NAMED
set file=%~n1%~x1
rem replace NAMED in src with nothing
set srctst=%src:NAMED=%
rem if src and srctst are still the same, copy
if %srctst%==%src% robocopy %src% %dst% %file% /move /create
goto :eof
After thorough testing, this works great. However, as it is a lot of files, you may want to set up a little test environment, like in your example, to use this on first, before you use it on your actual data.
setlocal enabledelayedexpansion
cd C:\rootfolder
for /f "tokens=*" %%a in ('dir /s /b /a:d') do (
attrib "%%a\*.*" | find "File not found"
if !errorlevel!==1 (
if not exist "%%a\Named" md "%%a\Named"
xcopy "%%a\*.*" "%%a\Named"
del "%%a\*.*" /f /q
)
)

Resources