Go Premium for a chance to win a PS4. Enter to Win

x
Solved

# Move only folders (and contents) which match a string?

Posted on 2009-07-07
Medium Priority
340 Views
I have a very large folder structure and need to find all subfolders with a certain keyword in them and then move those subfolders (including contents) to a new location.  For instance, say I have the following folders containing files of various types:

source\file1\bar\foo
source\file2\file3\bar\stuff
source\file3\foobar

Now, I want to move all folders with the word "foo" in them from 'source' to 'destination'.  The result I want is:
source\file2\file3\bar\stuff

destination\file1\bar\foo
destination\file3\foobar

I was looking at robocopy and xcopy but neither seem to give me the ability to move a folder and its contents based on search criteria without affecting nonmatching folders in the source location.  Any ideas?  Maybe I am missing something painfully obvious.
0
Question by:BBG-BBGM
• 5
• 5
• 5
• +1

LVL 39

Expert Comment

ID: 24795599
This should be easy enough to do using a FOR command that parses through the output from a filtered DIR listing of Folders in the source and runs the xcopy command sequentially for each folder name.  Something along these lines perhaps (don't use it, it's just an untested example off the top of my head):

@echo off
set SourcePath=C:\Some_Folder
set DestPath=G:\Some_Folder

for /f "tokens=* delims=" %%a in ('dir /on /ad /b /s "%SourcePath%" ^| find /i "foo"') do xcopy /switches "%%a\" "%DestPath%\%%a"

where the DIR listing for folder names only is searched for those with (case insensitive) "foo" in the name, and the resultant listing is used as the folder names for the xcopy command to "move" to the destination sequentially as it reads through the listing.

Before creating a proper and tested batch file, however, it is very important to know how you would wish to handle a folder with "foo" in the name when it is a sub-folder of a folder WITHOUT "foo" in the name, or where the folder WITH the "foo" in its name also has one or more SUB-Folders NOT containing "foo" in the names.

Are you seeking to recreate the same folder hierarchy as is in the Source path, or do you want to flatten it completely so that the Destination contains ONLY the matching folder names and any loose files in each folder, BUT NOT sub or master folders that DO NOT contain "foo" in the names?

As an example, say you have the following folders in the source:

C:\Folder1\Sub-Folder1
C:\Folder1\Sub-Folder1\Foo_Files1
C:\Folder1\Sub-Folder1\Foo_Files2
C:\Folder1\Sub-Folder1\Foo_Files2\Some_Other_Folder
C:\Folder1\Sub-Folder1\Other_Files\Foo_Files3\Stuff
C:\Folder1\Sub-Folder1\Other_Files\Foo_Files3\Stuff\Scripts

Would you want:
"Some_Other_Folder" copied to the destination still as a sub-folder of "Drive:\Folder1\Sub-Folder1\Foo_Files2"
OR would you just want to copy the "Foo_Files2" folder MINUS the sub-folder named "Some_Other_Folder"?

Similarly, would you want the "Foo_Files3" folder copied on its own just with files in it, or have the master folder copied to the destination with "Foo_Files3" still as a sub-folder, and also copy any sub-folders and contents to the destination maintaining the original folder structure?

Flatten folders or maintain folder hierarchy?
0

LVL 1

Author Comment

ID: 24795673
BillDL:
Thanks for the response.  I am looking to move the matching subfolders (including any subfolders regardless of name) to the destination with the entire original folder path.  Given your example (I modified it to show other outcomes):
C:\Folder1\Sub-Folder1
C:\Folder1\Sub-Folder1\abc
C:\Folder1\Sub-Folder1\Foo_Files1
C:\Folder1\Sub-Folder1\Foo_Files2
C:\Folder1\Sub-Folder1\Foo_Files2\Some_Other_Folder
C:\Folder1\Sub-Folder1\Other_Files\def
C:\Folder1\Sub-Folder1\Other_Files\def\stuff
C:\Folder1\Sub-Folder1\Other_Files\Foo_Files3\Stuff
C:\Folder1\Sub-Folder1\Other_Files\Foo_Files3\Stuff\Scripts

After running with 'SourcePath=C:\Folder1' and 'DestPath=G:\Folder2'  and keyword of 'foo' I would want to end up with:
C:\Folder1\Sub-Folder1
C:\Folder1\Sub-Folder1\abc
C:\Folder1\Sub-Folder1\Other_Files\def
C:\Folder1\Sub-Folder1\Other_Files\def\stuff

G:\Folder2\Sub-Folder1\Foo_Files1
G:\Folder2\Sub-Folder1\Foo_Files2
G:\Folder2\Sub-Folder1\Foo_Files2\Some_Other_Folder
G:\Folder2\Sub-Folder1\Other_Files\Foo_Files3\Stuff
G:\Folder2\Sub-Folder1\Other_Files\Foo_Files3\Stuff\Scripts

Does this help?
0

LVL 39

Assisted Solution

BillDL earned 300 total points
ID: 24795900
Yes it does, thanks.

I will create a test source and try to achieve what you want done using XCOPY.
0

LVL 16

Assisted Solution

t0t0 earned 300 total points
ID: 24795913
This was a tough one.... Phew!!

Rename the SOURCE, DESTINATION and FILESPEC values. DO NOT include trailing '\' (backslash) characters on the end of SOURCE nor DESTINATION.

copy and paste the code into Notepad and save it as MOVETREE.BAT. Then, fire up a DOS session and enter the following command:

MOVETREE

@echo off
setlocal enabledelayedexpansion

set source=c:\source
set destination=c:\destination
set filespec=foo

for /f "tokens=*" %%a in ('dir /ad /b /s "%source%"') do (
set folder=%%~nxa
set folder=!folder:%filespec%=!
if not "!folder!"=="%%~nxa" (
set s=%%a
set s=!s:%source%=!
for /f "tokens=1 delims=\" %%b in ('echo !s!') do (
move "%source%\%%b" "%destination%\%%b"
)
)
)
0

LVL 16

Expert Comment

ID: 24796103
In the code above, set the following values:

set source=c:
set destination=g:
set filespec=foo

0

LVL 16

Expert Comment

ID: 24796133
Sorry... I see c:\folder1 is your source and g:\folder2 is your destination therefore your settings should be as follows:

set source=c:\folder1
set destination=g:\folder2
set filespec=foo
0

LVL 1

Author Comment

ID: 24796186
t0t0:
Close, but not quite.  I ran the script with:
set source=d:\folder1
set destination=d:\folder2
set filespec=bulletin

On the following folder structure:
D:\Test1\folder1
D:\Test1\folder1\folder11
D:\Test1\folder1\folder12
D:\Test1\folder1\folder12\folderbulletin12
D:\Test1\folder1\folder12\folderno12
D:\Test1\folder1\folder12\folderbulletin12\bulletinstuff
D:\Test1\folder1\folder12\folderbulletin12\stuff
D:\Test1\folder2
D:\Test1\folder2\bulletindocument21.txt
D:\Test1\folder2\bulletinfiles21
D:\Test1\folder3
D:\Test1\folder3\folder31
D:\Test1\folder3\folder31\folder32
D:\Test1\folder3\folder31\folder32\afile.zip
D:\Test1\folder4
D:\Test1\folder4\folder41
D:\Test1\folder4\folder41\folder42
D:\Test1\folder4\folder41\folder42\bulletin42.psd

I ended up with:
d:\Test1\folder3
d:\Test1\folder3\folder31
d:\Test1\folder3\folder31\folder32
d:\Test1\folder3\folder31\folder32\afile.zip
d:\Test1\folder4
d:\Test1\folder4\folder41
d:\Test1\folder4\folder41\folder42
d:\Test1\folder4\folder41\folder42\bulletin42.psd

So far so good, since I don't mind if a filename has the string 'bulletin' in it... but the destination has unintended content:
d:\Test2\folder1
d:\Test2\folder1\folder11   <-- This one does not match
d:\Test2\folder1\folder12
d:\Test2\folder1\folder12\folderbulletin12
d:\Test2\folder1\folder12\folderno12  <-- This one does not match
d:\Test2\folder1\folder12\folderbulletin12\bulletinstuff
d:\Test2\folder1\folder12\folderbulletin12\stuff
d:\Test2\folder2
d:\Test2\folder2\adocument21.txt  <-- This one does not match
d:\Test2\folder2\bulletindocument21.txt  <-- File, not folder matching
d:\Test2\folder2\bulletinfiles21

It seems your script is copying the entire folder one level below where the folder matching 'bulletin' is appearing.  Great start though!

0

LVL 39

Expert Comment

ID: 24796275
Hee, hee.  I should have done this during the night when t0t0 was in bed sound asleep.  Good script so far t0t0.  I gave up trying xcopy.  I was using the /T switch just to try and create the empty folder structure in the destination before testing for real, but I was having difficulty maintaining the master folder in the structure when using %%~nxA.  I had just started off with a not-dissimilar idea using MOVE, but your script was written while mine was still conceptual.

I think I'll leave you to it t0t0.  You love this type of challenge, and so do I, but I need to have some dinner before going out to work.  You have the rest of the night after all essential domestic chores are done ;-)

0

LVL 16

Expert Comment

ID: 24796488
BillDL

You are a gentleman. Thank you.
0

LVL 21

Expert Comment

ID: 24798520
Give this a try.
@echo off
setlocal enabledelayedexpansion
set source=d:\folder1
set destination=d:\folder2
set filespec=bulletin

for /f "tokens=*" %%a in ('dir /ad /b /s "%source%\*%filespec%*"') do if exist "%%a" (
Set Found=%%a
move "%%a" "!Found:%source%=%destination%!"
)

0

LVL 1

Author Comment

ID: 24798816
AmazingTech:
Getting close with that one but it is not working.  It looks like line 9 is taking the path in %Found% and substituting the %source% for %destination% but that is not working.  Here is what I get during output:

D:\>if exist "d:\Test1\folder2\bulletinfiles21" (
Set Found=d:\Test1\folder2\bulletinfiles21
move "d:\Test1\folder2\bulletinfiles21" "!Found:d:\Test1=d:\Test2!"
)
The system cannot find the path specified.
0 file(s) moved.

So I guess we need to figure out how to get string substitution to work with variables?  I suppose I could hard-code it for now just to get it to work... let me know if you have any ideas.
0

LVL 21

Expert Comment

ID: 24798944
Hmm.. The replace should work. Do you have a destination folder D:\Test2?
Here's an echo of the source and destination.
@echo off
setlocal enabledelayedexpansion
set source=d:\folder1
set destination=d:\folder2
set filespec=bulletin

for /f "tokens=*" %%a in ('dir /ad /b /s "%source%\*%filespec%*"') do if exist "%%a" (
Set Found=%%a
Echo Source=%%a
Echo Destination=!Found:%source%=%destination%!
Echo Moving "%%a" "!Found:%source%=%destination%!"
move "%%a" "!Found:%source%=%destination%!"
)

0

LVL 16

Expert Comment

ID: 24798967
Hello AmazingTech....

My attention was redirected for a little whle however, I've returned and noticed you've joined us. I'm currently working on a solution however, please feel free to muck in.
0

LVL 21

Expert Comment

ID: 24799391

Add /y to the move if you want it to overwrite without prompting.
@echo off
setlocal enabledelayedexpansion
set source=c:\documents and settings\gordon\at
set destination=c:\folder2
set filespec=itunes

for /f "tokens=*" %%a in ('dir /ad /b /s "%source%\*%filespec%*"') do if exist "%%a" (
Set Found=%%a
Set Parent=%%~dpa
Echo Source=%%a
Echo Destination=!Found:%source%=%destination%!
Echo Parent="!Parent:%source%=%destination%!"
If not exist "!Parent:%source%=%destination%!" MD "!Parent:%source%=%destination%!"
Echo Moving "%%a" "!Found:%source%=%destination%!"
move "%%a" "!Found:%source%=%destination%!"
)

0

LVL 21

Accepted Solution

AmazingTech earned 1400 total points
ID: 24800750
Seems to work fine as long as the folders do not already exists.

c:\Test1\folder1\folder12\folderbulletin12

d:\Test2\folder1\folder12\folderbulletin12

It will move c:\Test1\folder1\folder12\folderbulletin12 to:
d:\Test2\folder1\folder12\folderbulletin12\folderbulletin12

The best might be to create the folder and then move to the parent. For some reason my machine is giving me Access is denied. I'm not too sure if it is just my machine. Maybe someone can try this as see if they get the same result.

I'll leave out the /y from

move "%%a" "!Parent:%source%=%destination%!"
@echo off
setlocal enabledelayedexpansion
set source=d:\folder1
set destination=d:\folder2
set filespec=bulletin

for /f "tokens=*" %%a in ('dir /ad /b /s "%source%\*%filespec%*"') do if exist "%%a" (
Set Found=%%a
Set Parent=%%~dpa
Echo Source=%%a
Echo Destination=!Found:%source%=%destination%!
Echo Parent="!Parent:%source%=%destination%!"
If not exist "!Parent:%source%=%destination%!" MD "!Parent:%source%=%destination%!"
Echo Moving "%%a" "!Parent:%source%=%destination%!"
move "%%a" "!Parent:%source%=%destination%!"
)

0

LVL 1

Author Comment

ID: 24803310
AmazingTech:
It seems to be working this time!  Not sure why the replace was not working before... but it is now.  There will be no pre-existing folders in the destination location so I should be good.  i am going to run it on the data now and see how it goes.  Oh, I like the echos in there too because I can redirect out to logfile.

Will let you know how it goes.
0

LVL 1

Author Comment

ID: 24806995
That worked like a charm!  Thanks to all for your great work!
0

LVL 21

Expert Comment

ID: 24808555
OK. Great! Thanks for the grade.
0

LVL 39

Expert Comment

ID: 24811878
Thank you BBG-BBGM
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

As most anyone who uses or has come across them can attest to, regular expressions (regex) are a complicated bit of magic. Packed so succinctly within their cryptic syntax lies a great deal of power. It's not the "take over the world" kind of power,…
This article was inspired by a question here at Experts Exchange (http://www.experts-exchange.com/Software/Photos_Graphics/Images_and_Photos/Q_28629170.html). The requirements stated in that question are (1) reduce the file size of a large number of…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
###### Suggested Courses
Course of the Month11 days, 10 hours left to enroll