Jump to content

Question regarding advanced "for" use in batch file


Recommended Posts

Hi guys,

maybe someone can help ... i would like to copy directories containing a defined set of names to a location using robocopy. So instead of using 20 robocopy commands I would like to use one line using the "for" command to cylce through a specific directory and copy only those directories matching a list of names.

Lets say the path is D:\Data and contains subdirectories like "001, 002, 003, 004 etc. Maybe these directories also contain subdirectories like 0001, 0002, etc.

I would like to have a list of directories in a file like

001,

002

0001

and the for command should just copy the content of directories matching the above names in the list.

Would that be possible or not ? Is there anyone able to help me with the solution ?

Thanks a lot in advance !

Alex

Link to comment
Share on other sites


Would that be possible or not ?

Yes.

Is there anyone able to help me with the solution ?

Yes.

http://homepages.tesco.net/J.deBoynePollard/FGA/questions-with-yes-or-no-answers.html

:whistle:

A Moderator may want to move this post to:

http://www.msfn.org/board/forum/66-programming-c-delphi-vbvbs-cmdbatch-etc/

Open a command prompt.

In it type:

DIR /B  /S /AD D:\DATA 

[ENTER]

What do you see?

Now type in it:

FOR /F %A IN ('DIR /B  /S /AD D:\DATA') DO @ECHO I'm in a FOR LOOP - %A

[ENTER]

What do you see?

Now go here and read these:

http://www.robvanderwoude.com/ntfor.php

http://www.robvanderwoude.com/ntfortokens.php

You should now have all the basics needed. :)

Try writing a batch with the info you just learned and with the robocopy command you would use manually, and we'll see what kind of enhancements (if any) we can suggest.

jaclaz

Link to comment
Share on other sites

One enhancement will be to use recursion to get to the subdirectories 0001, 0002, etc.

Cheers and Regards

What do you think the posted FOR loop example does, if not recursion? :unsure:

Or are you meaning the recursion (already) given by the /S parameter to DIR? ;)

jaclaz

Link to comment
Share on other sites

I wrote this Demo script for you to try. You will have to add

the folder name you want to check in this spot in the script.

Dim Chk :Chk = Array("Folder1", "Folder2")

Save As Demo_RecursiveFolder.vbs


Dim Fso :Set Fso = CreateObject("Scripting.FileSystemObject")
'-> Varibles For Run Time
Dim Arg, Dir, Obj, Ts, Txt, Var
'-> Array To Hold Folder Name To Check For
Dim Chk :Chk = Array("Folder1", "Folder2")
'-> Arg To Check If Any Matching Folder Found
Arg = False
'-> Script Report
Txt = Fso.GetFolder(".").Path & "\Report.txt"
Set Ts = Fso.CreateTextFile(Txt)
Ts.WriteLine " Scan Time : " & Time()
Ts.WriteLine " Scan Date : " & Date()
'-> Start Recursive From Script Current Location
'-> Recursive(Fso.GetFolder(".")) Or Add A Full Path
'-> EG Recursive(Fso.GetFolder("C:\SOME\FOLDER\PATH"))
Recursive(Fso.GetFolder("."))
'-> End Of The Script Report
Ts.WriteLine Var
Ts.Close
'-> Arg Check If Match Found
If Arg = True Then
'-> Open Report To Read
CreateObject("Wscript.Shell").Run("Notepad " & Chr(34) & _
Txt & Chr(34)),1,True
'-> To Keep Or Delete
If MsgBox("Did You Want To Keep This File?",4132,"Keep Or Delete") = 7 Then
Fso.DeleteFile(Txt),True
End If
Else
'-> No Match Found
MsgBox "Could Not Find Any Matching Folder In This Location" & vbCrLf & _
Fso.GetFolder(".").Path, 4128,"No Match Found"
Fso.DeleteFile(Txt),True
End If
'-> Recursive Threw All Sub Folders
Function Recursive(Folder)
'-> Loop Threw Check Folder And Check For A Match
For Each Obj In Chk
'-> Check For Folder Name Case Insensitive
If InStr(1,Folder.Path,Obj,1) Then
Arg = True
Var = Var & vbcrlf & _
"----------------------------------" & _
vbCrLf & "Match Found : " & Folder.Path & vbCrLf & _
"----------------------------------" & vbCrLf
End If
Next
'-> Loop Threw Sub Folders
For Each Dir In Folder.subFolders
Recursive(Dir)
Next
End Function

Change Name From Demo_RecursiveFolder.vbs.txt to Demo_RecursiveFolder.vbs to make active

Demo_RecursiveFolder.vbs.txt

Link to comment
Share on other sites

Or are you meaning the recursion (already) given by the /S parameter to DIR? ;)

No, I meant like this:


@ECHO OFF & SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _DirList=DesiredDirectories.txt
CALL :f_CopyDefinedDirs SpecificDir1 SpecificDir2 SpecificDir3
EXIT

:f_CopyDefinedDirs %_DirNames%
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:s_DoUntilNoMoreDirsToCheck
IF ['%1']==[''] ENDLOCAL&EXIT /B 0
IF EXIST %1 (
FINDSTR /i /x "%~n1" %_DirList%> nul && IF %ERRORLEVEL% EQU 0 (
REM
REM
REM Do your RoboCopy thing here
REM 'You might want to check to make sure the directory is not empty of files
REM first, but that is left as an exercise for the reader'
REM
REM
)
FOR /F "tokens=*" %%G IN ('dir /-B /AD %1') DO IF EXIST %1\%%G (CALL :f_CopyDefinedDirs %1\%%G)
)
SHIFT & GOTO s_DoUntilNoMoreDirsToCheck

Note: DesiredDirectories.txt should have each desired directory listed one per line. as in the OP's example. And yes I know that more error handling might be required depending on the directory structure he has to deal with.

Cheers and Regards

Edited by bphlpt
Link to comment
Share on other sites

Guys !

You are soooo wonderful. I didnt except soo much responsive!

I will look through your answers in detail, I am sure I will have some questions ...

I will get back to you, thanks sooo much for your help ! :thumbup

Have a great day !

Alex

Link to comment
Share on other sites

Hi again,

@gunsmokingman: thanks a lot for your vbs script. I would prefer to do it within a batchfile because the process is part of a larger already existing cmd backup script. But if I dont find a good way to do it within a cmd I will come back to your solution !

@Yzöwl: Attached is a screenshot of the directorystructure that I am trying to copy. Those are shadowcopy mountpoints created by DPM (Dataprotectionmanager) so one can copy files from DPM to for instance external Harddrives via non VSS aware scripts or applications. I do not have space on my external HD for all the mountpoints so my intention was to have a list of mountpoints that will then be copied from the directory structure to the USB harddisc like:

vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0

vol_a6f0c2c5-39d7-4e77-ae3b-b8f4fc835b8f

vol_1d53783a-0dcf-4d62-8f11-19c297af3de2

etc.

The script should go over the complete structure below the "C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy" Source directory and copy everythiing below the mountpoints mentioned inside the list.

@bphlpt:

Thanks so much for your script. Before I can test it ... robocopy expects a source to copy from ... where is this source variable in your script. I am amazed at your script, I can hardly understand every part of it so please excuse if I didnt check the obvious :)

Thanks guys and sorry for being such a lame a** with scripting .. I hope to learn more ! :)

Alex

post-23952-0-44598900-1314195153_thumb.j

Link to comment
Share on other sites

... robocopy expects a source to copy from ... where is this source variable in your script. I am amazed at your script, I can hardly understand every part of it so please excuse if I didnt check the obvious :)

Thanks guys and sorry for being such a lame a** with scripting .. I hope to learn more ! :)

IMHO in order to learn you need to start from the bottom and go up (as opposed to from the top and going down).

Say that you have ONLY contents oof a single folder to copy over (le'ts use this as an example):

C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0

WHICH robocopy command line would you use?

jaclaz

Edited by jaclaz
Link to comment
Share on other sites

Hi jaclaz,

well my robocopy command would be like this:


robocopy "%DPMSource%\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0" "%USB%\DPM\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0" %roboparametermirror%

Variables being:

DPMSource: Path to DPM Shadowcopy Volume

USB: Path to USB driveletter

robocopyparametermirror: /E /ZB /MIR /XD "System Volume Information" /XF "*.mp*" "*.avi" "*.mkv" "*.wm*" "*.m4*" /LOG+:"%LOG%" /TEE /NP

Link to comment
Share on other sites

Try something like this:

@ECHO off
SETLOCAL enableextensions disabledelayedexpansion

REM Set the two variables below
SET "LISTOF=Path to file with search list"
SET "USB=Path to USB drive"

SET "BRANCH=C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy"
(SET RCOPTS=/E /ZB /MIR)
(SET RCOPTS=%RCOPTS% /XD "System Volume Information")
(SET RCOPTS=%RCOPTS% /XF "*.mp*" "*.avi" "*.mkv" "*.wm*" "*.m4*")
(SET RCOPTS=%RCOPTS% /LOG+:"%LOG%" /TEE /NP)

SET "DESTIS=%USB%\DPM"

PUSHD %BRANCH%
FOR /d /r %%# IN (*) DO (
ECHO=%%~nx# | FINDSTR/ixg:"%LISTOF%" >NUL 2>&1 && (CALL :CopyIt %%#)
)
POPD
GOTO :Eof

:CopyIt
ROBOCOPY "%*" "%DESTIS%" %RCOPTS%

Link to comment
Share on other sites

Hi jaclaz,

well my robocopy command would be like this:


robocopy "%DPMSource%\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0" "%USB%\DPM\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0" %roboparametermirror%

Variables being:

DPMSource: Path to DPM Shadowcopy Volume

USB: Path to USB driveletter

robocopyparametermirror: /E /ZB /MIR /XD "System Volume Information" /XF "*.mp*" "*.avi" "*.mkv" "*.wm*" "*.m4*" /LOG+:"%LOG%" /TEE /NP

Good. :)

I guess we can change/semplify it to:

robocopy "%DPMSource%" "%USB_drive%\DPM\%DPMname%" %roboparametermirror%

Now let's assume that you have a plain text file like the following list.txt:

::Hello I am a senseless header, here only to show how you can skip lines in a FOR /F loop
C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy\vol_9edf29cf-c89a-4fe5-97d6-7c9ce70c13b0

And a batch file:


@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET USB_drive=U:
SET roboparametermirror=/E /ZB /MIR /XD "System Volume Information" /XF "*.mp*" "*.avi" "*.mkv" "*.wm*" "*.m4*" /LOG+:"%LOG%" /TEE /NP
FOR /F "skip=1 tokens=* delims=" %%A IN (list.txt) DO (
SET DPMSource=%%A
SET DPMName=%%~nA
ECHO robocopy "!DPMSource!" "%USB_drive%\DPM\!DPMname!" %roboparametermirror%
)

What happens?

What happens when you add some more source directories to list .txt and re-run the batch?

jaclaz

Link to comment
Share on other sites

@bphlpt:

Thanks so much for your script. Before I can test it ... robocopy expects a source to copy from ... where is this source variable in your script. I am amazed at your script, I can hardly understand every part of it so please excuse if I didnt check the obvious :)

jaclaz is trying to take you through the steps to learn the why and how, (kind of like school) so the next time you have a similar task you will know how to create the script for yourself. And Yzöwl obviously knows MUCH more about robocopy than I do. I would STRONGLY advise listening to them both and going through EVERY step they suggest. Consider it an honor that these teachers both are willing to spend the time with you.

To answer your question, in my script, "%1" would be the robocopy source, but its completeness and appropriateness as a path is dependent on how complete the "SpecificDirx" is. "%~n1" is the specific name that matched one of the members of your list. Yzöwl did a much more thorough job than I did on breaking down the robocopy command elements and the source and destination paths to make them all easier to handle.

Cheers and Regards

Link to comment
Share on other sites

Hi guys,

again, thanks for your help on this.

First I tried Yzöwl´s solution. I think it doesnt work because I am looking for names in the listfile that exist somewhere in the path not exactly at the top of the path in "C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy"

When I run that script I get a long running script with thousands of lines of output like this:


C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy\Microsoft Hyper-V VSS Writ
er>(ECHO=68EFFFA4-BAA3-4533-8627-D01B4A018078 | FINDSTR/ixg:"D:\Scripts\USB_Ba
ckup\shadowcopieslist.txt" 1>NUL 2>&1 && (CALL :CopyIt C:\Program Files\Micro
soft DPM\DPM\Volumes\ShadowCopy\Microsoft Hyper-V VSS Writer\vol_fa8b864b-234c-4
868-bd22-08b783b46fe6\c6f637b2-cdc2-4d4c-9e00-b48e200d296d\Full\D-Vol\secdom\Vir
tual Machines\68EFFFA4-BAA3-4533-8627-D01B4A018078 ) )

C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy\Microsoft Hyper-V VSS Writ
er>(ECHO=secdom | FINDSTR/ixg:"D:\Scripts\USB_Backup\shadowcopieslist.txt" 1
>NUL 2>&1 && (CALL :CopyIt C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCop
y\Microsoft Hyper-V VSS Writer\vol_fa8b864b-234c-4868-bd22-08b783b46fe6\c6f637b2
-cdc2-4d4c-9e00-b48e200d296d\Full\E-Vol\secdom ) )

My List of files looks like this:


Database Backups
DPMDB
Scripts
Acronis
Microsoft Exchange Writer
serv22
boomerang2
devtest02
UATWIN
Serv32
EX2010
TMG2010
Non VSS Datasource Writer
SqlServerWriter

These are directory names that exist somewhere in the directory structure below "C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy"

Then I tried Jaclaz solution:

At first I wasnt sure if the line


ECHO robocopy "!DPMSource!" "%USB_drive%\DPM\!DPMname!" %roboparametermirror%

Was correct or not ... shouldnt it be


ECHO robocopy "%DPMSource%" "%USB_drive%\DPM\%DPMname%" %roboparametermirror%

I tried both versions but the "!" instead of the "%" didnt work.

But even with the second version and a list file of just one line like


C:\Program Files\Microsoft DPM\DPM\Volumes\ShadowCopy\Database Backups

I get this output:


D:\Scripts\USB_Backup>FOR /F "skip=1 tokens=* delims=" %A IN (D:\Scripts\USB_Bac
kup\shadowcopieslist.txt) DO (
SET DPMSource=%A
SET DPMName=%~nA
ECHO robocopy "" "G:\DPM\" /E /ZB /MIR /XD "System Volume Information" /XF "*.m
p*" "*.avi" "*.mkv" "*.wm*" "*.m4*" /LOG+:""G:\copylog.txt"" /TEE /XD " /NP

)

Seems like the variables are not being read from the list file.

Hope you can help some more ...

If you have some time that is !

Have a nice saturday evening guys !

Alex

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...