Solved

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

Posted on 2009-07-07
19
318 Views
Last Modified: 2012-05-07
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
Comment
Question by:BBG-BBGM
  • 5
  • 5
  • 5
  • +1
19 Comments
 
LVL 38

Expert Comment

by:BillDL
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

by:BBG-BBGM
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 38

Assisted Solution

by:BillDL
BillDL earned 75 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

by:t0t0
t0t0 earned 75 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

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

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


0
 
LVL 16

Expert Comment

by:t0t0
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

by:BBG-BBGM
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\adocument21.txt
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 38

Expert Comment

by:BillDL
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

by:t0t0
ID: 24796488
BillDL

You are a gentleman. Thank you.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 21

Expert Comment

by:AmazingTech
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%!"

)

Open in new window

0
 
LVL 1

Author Comment

by:BBG-BBGM
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

by:AmazingTech
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%!"

)

Open in new window

0
 
LVL 16

Expert Comment

by:t0t0
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

by:AmazingTech
ID: 24799391
OK. I had to add in making of the parent folder.

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%!"

)

Open in new window

0
 
LVL 21

Accepted Solution

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

c:\Test1\folder1\folder12\folderbulletin12

For example if you already had this as a destination folder:
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%!"

)

Open in new window

0
 
LVL 1

Author Comment

by:BBG-BBGM
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

by:BBG-BBGM
ID: 24806995
That worked like a charm!  Thanks to all for your great work!
0
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24808555
OK. Great! Thanks for the grade.
0
 
LVL 38

Expert Comment

by:BillDL
ID: 24811878
Thank you BBG-BBGM
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

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,…
I have published numerous articles here at Experts Exchange that present programs/scripts written in a language called AutoHotkey. Each of those articles has a brief paragraph describing where to download the product and how to install it. I have al…
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…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now