Link to home
Start Free TrialLog in
Avatar of GGHC
GGHC

asked on

Batch script to copy several files from Source Folder to a Folder tree but only if the files exist.

Here is the scenario:

Desired result:
1) User places several files in Source folder
2) User launches Batch script
3) Script will take those source files and place then into a subtree of folders but only if the file exist in that specific folder. The files can be overwritten.
4) Once completed the script will move the sources files into completed folder.
 
Notes:
Each file placed in source will have different destination in the folder tree.
Users will be frequently adding folders in the destination folder tree (usually only one layer deep).

Ideally the script would be written using the FOR command and Robocopy since that is what I'm using for another part of the process.

Thanks in advance.
Avatar of JeffG2583
JeffG2583

Are you going to use a particular naming scheme to determine which folder these files will be moved to? If so, can you give some examples?
Avatar of GGHC

ASKER

Thanks for quick reply. There is no naming schema other the a relative name (which can change at any given time by the managers).
 
Sample structure
The desired script will take the file from c:\FormsUpdate and through the sub directories of c:\Master . If it finds a file with the exact name, it will overwrite it.



#Source
c:\Forms update\nameoffile1
c:\Forms update\nameoffile1

#Destination
c:\Master
c:\Master\Injury Forms\
c:\Master\Claims Forms\

#Current script take a mirror of C:\Master and mirrors it to c:\Vendors\[Name] using Robocopy /MIR
c:\Vendors
c:\Verndors\blabla
c:\Vendors\yipee
Few questions spring to mind before writing code:

How many files do you think might be in the destination dir and subdirs, are we ok to run a dir /s of the whole lot effectively?
Is a file likely to be in more than one dir, and if so presumably replace in all such dirs?
Are the files possibly in use during copying?

So roughly in code if you want to test for now before we do the actual copy ... also do we delete the updated file after it is copied?

@echo off
set source="C:\forms update"
set dest="C:\vendors"
set filelist="%temp%\filelist.txt"
REM Make destination file listing to save doing for each file - "filename.ext","path"
(for /f "tokens=*" %%A in ('dir /b /s /a-d %dest%\*.*') do echo "%%~nxA","%%~dpA") > %filelist%

REM loop through files in source dir, then look in above file list for directory to copy
for /f "tokens=*" %%s in ('dir /b /a-d %source%\*.*') do (
  echo Looking for files to update with %%s
  for /f "tokens=1,2 delims=," %%f in ('find "%%~s" ^<%filelist%') do (
    echo ... updating in %%~g directory... do robocopy here ...
  )
)

Open in new window

 


Steve
SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of GGHC

ASKER

Thanks Steve and oBda.
I tried both your suggestions an I don't see the modification going over.

Steve- I do see the Filelist get created and it looks correct.

oBda- I removed the Echo as you mentioned during the test.

Would just having 1 file at a time in the Source (c:\Forms Update\) simplify it? That is an acceptable solution also.
1)The user will place 1 file in the folder.
2) User will launch the script
3) the script will take that single file and replace it if it exist.
4) When the update is completed the script will move it to c:\Forms Completed\

Thanks for your help.
It's working just fine here, unless I misunderstood something.
Just in case: please do not start the script with a double-click from Explorer; open a command prompt, enter "cd /d P:\ath\to\the\script\folder" (you can use Tab to auto-complete folder names) or right-click the script folder in Explorer while holding down Shift, which should add "Open command prompt here" to the context menu; then start the script from the command prompt. This will let you see any output, including error messages.
Did the "copy" commands generated while the ECHO in line 10 was still there look OK? Should the actual target be "C:\Master" or "C:\Vendor", and if the latter, did you change it in the script as well?
Did my script produce any output? You should see something like this, with one line per file in the source folder:
ERROR: File 'test-notthere.txt' not found in target.
        1 File(s) copied.
OK: File 'test.txt' copied to 'D:\Temp\B\'.

Open in new window

Oh, and whether the script processes one file or more doesn't really matter.
With mine then you'd just have to add your copy, xcopy is fine, e.g. I just tried this.... can add >NUL to the end of the copy to hide the 1 file(s) copied etc.  It shows 0 file(s) copied if the file is the same at the mo.

@echo off
set source="C:\forms update"
set dest="C:\vendors"
set filelist="%temp%\filelist.txt"
REM Make destination file listing to save doing for each file - "filename.ext","path"
(for /f "tokens=*" %%A in ('dir /b /s /a-d %dest%\*.*') do echo "%%~nxA","%%~dpA") > %filelist%

REM loop through files in source dir, then look in above file list for directory to copy
for /f "tokens=*" %%s in ('dir /b /a-d %source%\*.*') do (
  echo Looking for files to update with %%s
  for /f "tokens=1,2 delims=," %%f in ('find "%%~s" ^<%filelist%') do (
    echo ... updating in %%~g directory...
    xcopy "%source%\%%~f" "%%~g" /y /d
  )
)

Open in new window

 
User generated image
Will adjust tomorrow but mine only checks the filename exists in that file, so for example abc123.txt would also match xyzabc123.txt.

can change easily to look for complete filename, 1:30am here so not now!
Ok try this instead then.

@echo off
set source="C:\forms update"
set dest="C:\vendors"
set filelist="%temp%\filelist.txt"
REM Make destination file listing to save doing for each file - "filename.ext","path"
(for /f "tokens=*" %%A in ('dir /b /s /a-d %dest%\*.*') do echo "%%~nxA","%%~dpA") > %filelist%

REM loop through files in source dir, then look in above file list for directory to copy
for /f "tokens=*" %%s in ('dir /b /a-d %source%\*.*') do (
  echo Looking for files to update with %%s
  for /f "tokens=1,2 delims=," %%f in ('findstr /b /l /i "\"%%~s\"," "%filelist%"') do (
    xcopy "%source%\%%~f" "%%~g" /y /d | find "1 File(s) copied" && echo ... updating in %%~g directory...
  )
)

Open in new window


D:\>new
Looking for files to update with y.txt
1 File(s) copied
... updating in d:\temp\ directory...
1 File(s) copied
... updating in d:\temp\x\ directory...
1 File(s) copied
... updating in d:\temp\x\z\ directory...

D:\>new
Looking for files to update with y.txt

D:\>

Open in new window

Because of
4) Once completed the script will move the sources files into completed folder.
would'nt it be better to replace XCOPY by MOVE?
A good point Qlemo

I also thought if we process %1 then a file dragged onto the icon would process one file for them too, if not process source dir.

Steve
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of GGHC

ASKER

Guys,
I need to reopen this. I came across a hurdle I need your help on.
Below is the final script. I came across an issue that while it's processing the FOR loop, it actually moves the file (line 12) after the 1st one completes, therefor any subsequent copies will fail because it can find the file (because it was moved).

I would like it to move to the %Completed% only after it copied to all the folders that contain the existing file.
If there is no match of that file, it will remain in the %Source% folder


@echo on
setlocal enabledelayedexpansion
set Source=c:\some_path\Forms update
set Mask=*.*
set TargetRoot=c:\some_path\Master
Set Completed="c:\some_path\Forms Update Completed\"
for %%s in ("%Source%\%Mask%") do (
      set Found=False
      for /f "delims=" %%f in ('dir /s /b /a:-d "%TargetRoot%\%%~nxs" 2^>NUL') do (
            set Found=True
            copy "%%s" "%%~dpf"
            move /y "%%s" %Completed%
            if errorlevel 1 (
                  echo ERROR: File '%%~nxs' could not be copied to target.
            ) else (
                  echo OK: File '%%~nxs' copied to '%%~dpf'.
            )

      )
      if !Found!==False (
            echo ERROR: File '%%~nxs' not found in target.
      )

)
I think then you just need to move than line to here:

move /y "%%s" %Completed%

if !Found!==False (
            echo ERROR: File '%%~nxs' not found in target.
      ) ELSE (
               move /y "%%s" %Completed%
      (
Avatar of GGHC

ASKER

Looked good with the test. Thanks!