# Solved: Help with For /r loop



## mcwilsong (Jun 9, 2009)

I wrote a batch file to make a copy of a file and add "_wgs" to the file name (not the extension). However, I don't know whether the folders (which could number 300 or so and contain 29 or more sub folders each) if there are any existing files already with a "filename_wgs.shp" name. I have to assume that since I haven't run my batch on the folder yet, that the file was created manually and I don't want to overwrite it.
I would like the command that creates the copy to take into account all *.shp files in the loop, but exclude anything that already contains "_wgs.shp" in the file name.

I tried using the /-Y, but it requires a manual reply and I don't want to use /Y because, as I said earlier, I don't want to overwrite the file. This is what I started with:

for /r %%i in (*.shp) do copy "%%i" "%%~pni_wgs.shp"

It works great, however, I realized that there are sub directories I want to skip as well. So I figured I'd move copy into xcopy. However, this does not work:

for /r %%i in (*.shp) do xcopy %%i %%~pni_wgs.shp /t /e /Exclude:excludelist.txt

excludelist.txt contains:
left (hoping that it would exclude every folder name that has "left")
right (hoping that it would exclude every folder name that has "right")
wgs.shp (hoping that it would exclude every file name that has "wgs.shp")

All I get is a "Cannot perform a cyclic copy" error. Is what I'm trying to do even possible as the command stands? I'm trying to keep it as simple as possible. Any help would be greatly appreciated!

Glenn


----------



## TheOutcaste (Aug 8, 2007)

Welcome to TSG!

When using Xcopy and copying a directory tree, the destination can't be a subfolder of the source. While the For /r loop is returning single file names, the /T and /E switches tell Xcopy that it's copying a tree, so it gives the cyclic copy error.
You've left off the *d* modifier, so there is no drive letter specified in the Destination. It will still work, but in some situations, that can give unexpected results, so best to include it: %%~*d*pnI

If you remove the /E and /T switches, you'll get another prompt for each file:
*Does C:\Test\filename_wgs.shp specify a file name
or directory name on the target
(F = file, D = directory)?*

Xcopy was meant to copy files, not rename them. When copying single files, it expects the Destination to be a folder name ending with \. If you don't have the \, it gives the above prompt. So if you want to rename the file, there is no way to avoid the prompt.

And neither example will overwrite an existing file. If *filename_wgs.shp* exists, your code will copy it to *filename_wgs_wgs.shp*.

Your best bet is to use a Dir command, pipe it to Findstr to remove the folders you want to exclude, then pipe it to a 2nd Findstr to exclude files that already have the *_wgs* added to their name

You then check if *filename_wgs.shp* already exists, and if not, then copy the file.

This should do the trick:

```
Set _root=C:\Test
PushD %_root%
For /F "delims=" %%I In ('Dir /A-D /B /S *.shp^|Findstr /I /V /G:excludelist.txt^|Findstr /E /I /L /V "_wgs.shp"') Do If Not Exist "%%~dpnI_wgs.shp" Copy "%%I" "%%~dpnI_wgs.shp"
PopD
```
If *excludelist.txt* is not in the _root folder (C:\Test in this example), you'll need to specify the path to the file.
To specify a folder name in *excludelist.txt*, best to use *\foldername\* format, or you may get partial matches and exclude folders you didn't intend to.
For example, if you put *folder1* in the *excludelist.txt* file, it will exclude *folder1*, *folder1**1*, *folder1**mustbeincluded*, and *do**folder1**25now*.
*\folder1\* will only exclude *folder1*.

HTH

Jerry


----------



## mcwilsong (Jun 9, 2009)

Excellent! Thank you very much Jerry ... that did work perfectly. One more question ... if I exclude the path part, is there any harm in just running the batch file at the root of the folder structure you want to effect?

I was just thinking, in terms of ease of use, by copying and pasting the appropriate batch files (in my case: copy_shp.bat, copy_shx.bat, copy_dbf.bat, copy_wgs.bat, excludelist.txt) to the root directory and then running them by calling copy_wgs.bat, someone else using the set of files wouldn't need to alter anything if performing the same function.


----------



## TheOutcaste (Aug 8, 2007)

The Set, PushD and PopD are only needed if the folders you want to work on are not the same as the one the batch file is in, so all you need is the For statement and put the file in the folder you want to work on.


----------

