Batch file to copy list of files including subdirectories - batch-file

I often have to track down files at work, pulling a hundred or so out of a list of a thousand, so I created a batch file that would copy the files in a location that are listed in a csv in the batch files directory and then paste them in a folder on my desktop.
This worked, but I often have to do this for hundreds of files across a dozen or so directories, so I tried to modify it to include subdirectories. I'm having an issue getting it to work and I was wondering if the excellent people at StackOverflow could help. Thanks!
#echo on
set theDest="%USERPROFILE%\Desktop\Batch Copies %date:/=%"
set /p MY_TEXT=<FileList.csv
echo.%MY_TEXT%
set MY_TEXT=%MY_TEXT:"",""=,%
echo.%MY_TEXT%
if not exist %theDest% md %theDest%
pause
for /R %MY_TEXT% %%G IN (.) do (
for /F "skip=1 delims=" %%f in (FileList.csv) do (
if exist "%MY_TEXT%\%%f.*" (
copy "%MY_TEXT%\%%f.*" %theDest%
) else (
if exist "%MY_TEXT%\%%f" (
copy /R "%MY_TEXT%\%%f" %theDest%
) else echo "%MY_TEXT%\%%f" does not exist && echo 0 file^(s^) copied. && echo ERROR: %%f not found && echo. && pause)
)
)
echo. && echo. && echo Process Completed. &&echo.
pause
Part of the problem is I was just getting into batch when I wrote this and then left it and am trying to come back and figure out how everything works so I've probably messed it up more ways than one.

So the FOR loop has a /R option which will run the same command across all subdirectories.
In your case, I think you want:
for /R %%a in (.) do call :MyCopyFunction %%a
exit /B
:MyCopyFunction [%1 is the current directory]
echo My Current directory is %1
[Do All your code here, using %1 as the current directory]
exit /B
I don't understand what your script is doing in detail, so you still have to fill in the details.
But this shows you how to traverse the entire directory structure.

Related

How do you search through a directory and take actions?

I am looking to make a batch file which will sift through a directory full of computer backups. The file format is "computername-date." Since I know the computer name is static, I need to find and take that directory so I can restore it's contents.
I never realized that for loops are so foreign from what I play with in other languages, so I find myself getting nowhere anytime soon.
REM First mount the drive that contains the backed up files
net use P: \\DC1\Shared\1Backups
REM Get the computer's name so we know what PC backup to use.
set SaveDirectory=%computername%
REM For each folder in the directory, do this when the computer name is found.
FOR /R "P:\" %%G in (%SaveDirectory%*) DO (
REM Restore files
echo found it.
REM Copy subdirectories into User Folder
mkdir P:\UGH
)
REM Dismount drive
The problem with what I have now is that when I run the code, the DO never runs. It should find that there is a folder called "INTERN-6.21.2019" by searching "INTERN*"
My impression of the for statement may be wrong. I need it to search through the P:/ Directory, not the subfolders. Compare the folder names to the SavedDirectory, then do something when they match. What am I doing wrong?
I've normally had good results with using CALL statements to invoke a subroutine rather than running items inside ( ).
The trick here is that you need to pass arguments to the the subroutine. Typically you'd pass the variable(s) you use in your FOR statement. These are referenced using %1 (or %1 %2 %3 if you have multiple things to pass) because these act like command line arguments. To exit the subroutine you then jump to EOF which then returns control to your FOR loop. After your FOR loop, don't forget to jump over your subroutine or you'll execute it again. In the example below I jump to :end, but you certainly could jump to somewhere else to do more things.
So using this methodology, your code might be like this:
set SaveDirectory=%computername%
FOR /R "P:\" %%G in (%SaveDirectory%*) DO CALL :process %%G
Goto :end
:process
REM Processing goes here
goto :end
:end
Hope this helps
This might get you going. This will find the "newest" directory. It is not clear from the question exactly what is to be copied and to where.
SET "MOSTRECENT=unknown"
FOR /F "delims=" %%d IN ('DIR /B /A:D /O:D "P:\%COMPUTERNAME%*"') DO (
SET "MOSTRECENT=%%~fd"
)
ECHO The most recent backup is "%MOSTRECENT%"
IF EXIST "MOSTRECENT" (COPY ...
This answer is based upon my understanding of what you're trying to do, copy a network directory named with the computername and a datestring, (with todays date), to another location:
#PushD "\\DC1\Shared\1Backups" || GoTo :EOF
#For /F "EOL=DTokens=1-3" %%A In (
'WMIC Path Win32_LocalTime Get Day^,Month^,Year'
)Do #For /F Tokens^=* %%D In ("%%C"
)Do #XCopy "%COMPUTERNAME%-%%B.%%A.%%D" "P:\UGH\" /H /R /K /Y>NUL 2>&1
#PopD

Batch - Copying & Naming

EDIT: Updated the Code with "Stephan" Edits. I tested some dummy files and everything seems to work. Thanks for taking the time out getting this fixed and working. I can now focus on moving forward on projects instead of getting outdated game development tools working. This was for the Source Engine SDK to help get game models loaded correctly with backwards compatibility.
"sodacan.dx90.dx80.vtx" should be "sodacan.dx80.vtx".
"sodacan.dx90.sw.vtx" should be "sodacan.sw.vtx".
ORIGINAL POST:
This batch file is suppose to restore missing vtx files by copying an existing vtx file. But the vtx files require a special prefix attached to them before the extension, such as "sodacan.dx80.vtx" and "sodacan.sw.vtx".
The Problem is that the script is not working as it should. The script is ran on a folder that contains VTX files with different names. The script is suppose to create copies of a single vtx file and name them. The example below shows what you start out with and the end result.
You start out with the original, such as
sodacan.dx90.vtx (Original File)
You should end with
sodacan.dx90.vtx (Original File)
sodacan.dx80.vtx (Copy 1)
sodacan.sw.vtx (Copy 2)
But I actually get this from the code.
awning001a.dx90.vtx (Original File)
awning001a.dx90.sw.vtx (Copy 1)
awning001a.dx90.dx80.vtx (Copy 2)
These files work with there associated MDL File, such as (sodacan.mdl) but the script does not touch those files at all.
Below is the code in the batch file
#ECHO OFF
echo Initiating VTX re-construction...
set /a count=0
for /r %%F in (.) do (
Pushd %%F
for %%i in ("*.vtx") do (
for %%j in ("%%~ni") do (
echo Fixing "%%~ni.mdl".
if not exist "%%~nj.dx80%%~xi" copy "%%i" "%%~nj.dx80%%~xi" && set /a count+=1
if not exist "%%~nj.sw%%~xi" copy "%%i" "%%~nj.sw%%~xi" && set /a count+=1
)
)
popd
)
echo %count% reconstructed VTXes.
pause
Replace your for %%i loop with the following:
for %%i in ("*.vtx") do (
for %%j in ("%%~ni") do (
echo Fixing "%%~ni.mdl".
if not exist "%%~nj.dx80%%~xi" copy "%%i" "%%~nj.dx80%%~xi" && set /a count+=1
if not exist "%%~nj.sw%%~xi" copy "%%i" "%%~nj.sw%%~xi" && set /a count+=1
)
)
and at the end use:
echo %count% reconstructed VTXes.
Changes to your code:
process only the desired extension instead of processing all files and compare the extension with an if
Check if the destination file exists before copying
increment the counter only, if there was a copy
take care of the proper filenames (two dots) with another for %%j (effectively removing two "extensions")
adapted the last echo line to include the counter
(and don't forget to popd at the end of your for /R loop - there is just a limited stack for pushd and without popd you might run into that limit, generating an errormessage and exiting the script)

Create Folder and SubFolder based on file name using batch file

Coding is not my speciality but I have come across a problem and google search has guided me to using batch file process in solving it. Essentially I have a couple of thousands of files that need to be moved into folders and they have a very simple file structure, listed below:
UK--London--Filename.pdf
UK--London--Filename2.pdf
UK--Manchester--Filename3.pdf
UK--Liverpool--Filename4.pdf
UK--Chester--Filename5.pdf
I would like the script to:
1. Pick up the first "--" check if the folder exists, if not create it
2. Pick up the second "--" check if the folder exists, if not create it
3. As there might be more than two "--", ignore the rest
4. Move file into the subfolder
To that end, the output should be some like (note "FILETEST" is the folder I am using to test the script):
C:\FILETEST\UK\London\UK--London--Filename.pdf
C:\FILETEST\UK\London\UK--London--Filename2.pdf
C:\FILETEST\UK\Manchester\UK--Manchester--Filename3.pdf
C:\FILETEST\UK\Liverpool\UK--Liverpool--Filename4.pdf
C:\FILETEST\UK\Chester\UK--Chester--Filename5.pdf
I have had an attempt to re-using a script from another question in stackoverflow (Batch create folders based on part of file name and move files into that folder). I understand that it would not do exactly what I need, but cant seem to get any output.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\FILETEST"
PUSHD %sourcedir%
FOR /f "tokens=1*delims=--" %%a IN (
'dir /b /a-d *.*.*'
) DO (
ECHO MD %%a
ECHO MOVE "%%a.%%b" --\%%a\
)
POPD
GOTO :EOF
Apologies for any headaches caused, I am hoping this is a simple one to solve.
Thank you,
Panos
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\FILETEST"
PUSHD %sourcedir%
FOR /f "tokens=1,2*delims=-" %%a IN (
'dir /b /a-d *--*--*.*'
) DO if "%%c" neq "" (
ECHO MD "%%a"
ECHO MD "%%a\%%b"
ECHO MOVE "%%a--%%b--%%c" ".\%%a\%%b\"
)
POPD
GOTO :EOF
Read the directory list of files in the current directory, (/a-d = no directorynames) that match *--*--*. Tokenise so that %%a acquires the part before the first --sequence, %%b the second and %%c the remainder.
If %%c is not empty then make the directories ".\%%a" and ".\%%a\%%b" (quoted because any spaces in the name would otherwise be seen as "create two directories") then move the file, again quoted for the same reason.
Note that each character individually between delims= and the close-quote is a delimiter - a delimiter-string is not supported. Consequently, this code will pick up - as well as --- and any other sequence of - and try to process it. You could gate the create/move further by adding if exist "%%a--%%b--%%c" directly after the if "%%c" neq ""before the (.
The md will create a directory if the target name does not already exist, and produce an error-message if it already exists. To suppress the error message, append 2>nul to the md lines.

search for partial folder name and return dir to use with batch

Firstly i am still a beginner at scripting so please be gentle.
I am creating a back up script and I want to be able to search network for part of a file name (which located on a networked External HDD for Backup use), then return the dir to use later to back up the contents of a USB device.
The folder name I am searching for consists of 4 elements as follows: Date-1234567-Type-User.
The part i am looking to search for is the 7 digit id number which is unique where as the other elements may be duplicated a number of times.
the current script i have been using is not returning anything it is giving file not found, could someone point me in the right direction my script is as follows, also i am working on windows 7.
#echo off
:start
set /p path=enter id no.:
for /r %%# in (.) do (
Echo %%~nx# | find "string" "%path%" 1>NUL && (
Echo Full Path: %%~nx#
Echo Filename : %%~nx#
Echo Directory: %%~p#
)
)
if defined p (
echo %p%
) else ( Echo file not found
)
pause
goto backup
:backup
if not exist "%p%"\"usb download" md "%p%"\"usb download"
if exist (
xcopy /y "USB" "%p%"\usb download
)
pause
goto start
the Xcopy lines work on their own creating a new folder and copying the contents however i have to write the complete file path manually which is quite extensive and laborious so if i could automate this it would help dramatically.
I thank you for your help in advance, I have googled and searched my heart out, but as I said I am a beginner and my brain is melting.
thanks all.
for /f "delims=" %A in ('dir /ad /b /s z:\*1234567*') do echo %A
This should find it.

Batch script that moves each file in a folder into their own folders named after the file?

So if I have
/folder/file1.txt
/folder/file2.jpg
/folder/file3.py
I want to create
/folder/file1/file1.txt
/folder/file2/file2.jpg
/folder/file3/file3.py
I have this batch file (be careful where you run it), which mostly works but if there is whitespace in the file name, the folder name will only be named up until the whitespace and so the file won't be moved inside of it.
Also, I only got it to work by arbitrarily putting the word "Folder" or some random string at the end of the folder name, if I exclude that, for some reason it won't work. I'm on windows 7.
#echo off
for /f %%a in ('dir /a-d /b') do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a"
)
goto :EOF
:func
set file=%~1
set dir=%file% Folder
md "%dir%" Folder 2>nul
move "%file%" "%dir%"
goto :EOF
Any ideas on how to address the whitespace/name issues? Thanks in advance.
#echo off
for /f "usebackq delims=?" %%a in (`dir /a-d /b`) do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a"
)
goto :EOF
:func
set file=%~1
set dir=%file% Folder
md "%dir%" Folder 2>nul
move "%file%" "%dir%"
goto :EOF
By setting the delims=? you are saying that your delimiter is a ? to split up a string, instead of the whitespace character, which allows you to read full file names with spaces in them. Usebackq means that you instead use ` around the command to be ran, which to me, just makes it more logical to read and understand "Hey, I'm actually executing this string."
To avoid problems with spaces in paths/file names, double quote all the references to them.
The reason for having to include a string at the end of the folder in your code is you are trying to create a folder with exactly the same name that the file (in your code, you are not removing the extension), and you can not have two elements (files or folders) inside a folder with the same name.
#echo off
for %%a in ("c:\folder\*") do (
if not "%%~fa"=="%~f0" (
if not exist "%%~dpna\" echo md "%%~dpna"
if exist "%%~dpna\" echo move /y "%%~fa" "%%~dpna"
)
)
For each file in the indicated folder
if the file is not the batch file
if not exist a folder with the same name that the file, create it
if the target folder exist, move the file to the folder
%%~fa = full path of the file being processed
%~f0 = full path of the batch file
%%~dpna = drive, path, and file name without extension of the current file being proccesed
In this code, the reason for the third if is to check if the possible previous folder creation has failed. If you have a file with no extension, you will not be able to create the folder, as it will have exactly the same name as the file and this is not allowed.
Code includes echo commands before md and move to show what will be executed. If the output is correct, remove the echo to make it work.

Resources