[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 722
  • Last Modified:

Select folders alphabetically in batch file?

Hi All,

I am trying to create a batch file that creates symbolic links based on a selection of folders.  The problem I am having is selecting the folders that I want to create the symbolic links from.

Here is an example of what I mean.  I have Drive P: which has the following folders:

Pathfinder
Pathology
Patton
Paul
Payback

What I want to do is for symbolic links to be made from say Pathfinder to Patton alphabetically.  The code I currently have is here and can only select a folder based on a name filter.  Is there a filter or way of sorting that will allow me to do this?  This is the code I have.
SET target="C:\Downloads\Symlink"
SET filter="Music"

forfiles /s /m %filter% /c "cmd /c IF @isdir==TRUE mklink /D %target%\@relpath %cd%\@relpath"

Open in new window

0
robclarke41
Asked:
robclarke41
  • 11
  • 7
  • 6
3 Solutions
 
Steve KnightIT ConsultancyCommented:
I prefer using a for loop with output of dir command as then you can control it fully. Remove the capitalised ECHO to do the commands, at the moment it will show them only.

If you can get dir command to show you what you want, e.g.

dir /b /s /ad  will show all dirs under a subdir
dir /b /s /ad music* will show all dirs under a subdir starting with music

@echo off
SET target=C:\Downloads\Symlink
SET filter=*

REM Bare dir listing of all dirs only under the current starting dir
Set Dir=dir /b /ad %filter%

for /f "tokens=*" %%A in ('%dir%') do ECHO mklink /D "%target%%%~pnA" "%%~fA"

Open in new window


Add /s to the Dir variable to do it for all subdirs like your forfiles command
Change filter to Music* to pick out just ones with Music in the name.

Steve

[Edit meant to use %dir% not %dircmd% as variable as %dircmd% is reserved]
0
 
robclarke41Author Commented:
Thanks Steve so how do I select a range alphabetically? This is what I'm trying to achieve.
0
 
QlemoC++ DeveloperCommented:
With a filter of Pat* you will get only those folders. If you need a more complex filter than one using simple pattern matching, you'll need more effort. E.g. for including Paul:
@echo off
SET target=C:\Downloads\Symlink

for /f "tokens=*" %%A in ('dir /b /a:d Pa* ^| findstr /b "Pa[tu]" ') do ^
for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"

Open in new window

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
QlemoC++ DeveloperCommented:
With a more specific selection by just enumerating dirs to use, just write up those in a FOR:
@echo off
SET target=C:\Downloads\Symlink

for %%A in (Pathfinder Patton Payback) do ^
for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"

Open in new window

0
 
robclarke41Author Commented:
Thanks for all the help! How would I do this as a range though rather than specifying the folders? So for example I could include all folders from pathfinder to payback?
0
 
QlemoC++ DeveloperCommented:
The first code snippet I posted does show that. You need to know what is in common, as ranges can only be defined if you are able to provide a valid regular expression (complex) or simple pattern for pattern matching (more obvious and easy). dir can only use simple pattern matching using ? for "any arbitrary character at this position" and * for "any amount (including zero) of arbitrary characters here". findstr can be used to apply more complex filtering using RegEx.

Another idea, and that is probably what you are after and in need for e.g. going thru "Pathfinder" to "Obsolete" and hence having a real range of consecutive names you cannot describe well with RegEx:
@echo off
SET target=C:\Downloads\Symlink
set first=Obama
set last=Reagan
set matched=

for /D %%A in (*) do (
  if "%%A" == %first" set matched=yes
  if defined matched for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"
  if "%%A" == "%last%" set matched=
)

Open in new window

This ignores all folders until reaching the "first" one. It then goes thru all subfolders. If "last" is hit, no more subfolders will get processed (while still checking for the folder names unnecessarily to keep it "structured programming" without using goto).
0
 
robclarke41Author Commented:
Thanks for this Qlemo, I'm getting 'The syntax of the command is incorrect' when running the script though?  Is there something else I need to do?
0
 
QlemoC++ DeveloperCommented:
I had two typos in my code:
@echo off
SET target=C:\Downloads\Symlink
set first=Obama
set last=Reagan
set matched=

for /D %%A in (*) do (
  if "%%A" == "%first%" set matched=yes
  if defined matched for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"
  if "%%A" == "%last%" set matched=
)

Open in new window

Of course you then need to change the values for "first" and "last" in lines 3 and 4 to your respective folder names.
0
 
robclarke41Author Commented:
Thanks, the script now runs without any errors (I have also changed the first/last values).  However nothing happens?  In the C:\Downloads\Symlink directory there is nothing?
0
 
QlemoC++ DeveloperCommented:
The script looks in the current directory, and probably that is not where your folders are. You can provide the full or relative path in line 7, but we then need to modify the script slightly:
@echo off
set src=C:\Temp 
set target=C:\Downloads\Symlink
set first=Obama
set last=Reagan
set matched=

for /D %%A in (%src%\*) do (
  if "%%~nxA" == "%first%" set matched=yes
  if defined matched for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"
  if "%%~nxA" == "%last%" set matched=
)

Open in new window

%src% now contains the path to the folders to check.
0
 
Steve KnightIT ConsultancyCommented:
Qlemo, presumably if you didn't find Obama or Reagan then it wouldn't start and/or complete?

Perhaps using GEQ instead of == for the first IF's, and GTR for the second and stopping, i.e.

for /D %%A in (%src%\*) do (
  if "%%~nxA" GEQ "%first%" set matched=yes
  if "%%~nxA" GTR "%last%" exit /b
  if defined matched for /F "tokens=*" %%B in ('dir /b /s %%A\') do ECHO mklink /D "%target%%%~pnB" "%%~fB"
)

Open in new window


But I'm still confused what is wanted as such?  The original code suggested subdirs, and this code is now filtering on the top level dirs then making a link for each dir under that.  If only creating a link at the top level then you should only need the top level dir link created, i.e.

for /D %%A in (%src%\*) do (
  if "%%~nxA" GEQ "%first%" set matched=yes
  if "%%~nxA" GTR "%last%" set matched=
  if defined matched ECHO mklink /D "%target%%%~pnA" "%%~fA"
)

Open in new window


Can you give us examples of the folder structure showing which dirs you do/don't want including please?

Steve
0
 
robclarke41Author Commented:
Hi Steve,
Sure no problem.  So I have a network drive mapped to a NAS unit, the drive is mapped as P:

P:\ has several subfolders ranging from A-Z alphabetically.

I want to make Symbolic Links of a range of these folders, say from Alpha to Papa.  The reason I cannot include the entire folder is that I want to sync the data from the range to an external disk.  I cannot run the sync on the entire disk as there is nowhere near enough space.

So if I could specify in the script the from folder and the to folder in the range alphabetically and have the script make symbolic links for all of those folders in the target location we have a winner!

I hope that makes sense?!

Thanks for your help so far guys.
0
 
QlemoC++ DeveloperCommented:
My bad. Of course a symbol link to the top level folders is correct. So Steve's last code is appropriate, even allowing providing (inclusive) limits for folder names which do not really exist, like "Pa" to "Quo". Putting it together:
@echo off
set src=C:\Temp 
set target=C:\Downloads\Symlink
set first=Obama
set last=Reagan
set matched=

for /D %%A in (%src%\*) do (
  if "%%~nxA" GEQ "%first%" set matched=yes
  if "%%~nxA" GTR "%last%" set matched=
  if defined matched ECHO mklink /D "%target%%%~pnA" "%%~fA"
)

Open in new window

or
@echo off
set src=C:\Temp 
set target=C:\Downloads\Symlink
set first=Obama
set last=Reagan
set matched=

for /D %%A in (%src%\*) do if "%%~nxA" GEQ "%first%" if "%%~nxA" LEQ "%last%" ECHO mklink /D "%target%%%~pnA" "%%~fA"

Open in new window

0
 
Steve KnightIT ConsultancyCommented:
On a different level though.... are you making these symbolic links to part of the drive so that you can then do a robocopy or something?

Steve
0
 
robclarke41Author Commented:
Hi Guys, I just ran again and rather encouragingly I got the following:
mklink /D "C:\Downloads\Symlink\Alpha" "c:\Alpha"
mklink /D "C:\Downloads\Symlink\Beta" "c:\Beta"
mklink /D "C:\Downloads\Symlink\Books" "c:\Books"
mklink /D "C:\Downloads\Symlink\Charlie" "c:\Charlie"

Open in new window

Strangely though nothing happened, I did run a single line to make sure symbolic links were working etc. and it worked fine so I'm not sure what's happening here?

Steve, yes I use an app called Allway Sync that should work fine with this setup.  Just need these link sorted!
0
 
QlemoC++ DeveloperCommented:
We still have the ECHO in place here, so the command will not be executed, only echoed to the screen. Remove ECHO to allow to perform the magic!
0
 
robclarke41Author Commented:
Now I'm confused! If I take the ECHO out I get:

 
The system cannot find the path specified.
The system cannot find the path specified.
The system cannot find the path specified.

Open in new window


Doesn't make sense as with the ECHO on it seems to be performing the right tasks as above?
0
 
robclarke41Author Commented:
Just to let you know how I'm testing:

set src=C:\
set target=C:\Downloads\Symlink
set first=Alpha
set last=Charlie
set matched=

for /D %%A in (%src%\*) do (
  if "%%~nxA" GEQ "%first%" set matched=yes
  if "%%~nxA" GTR "%last%" set matched=
  if defined matched mklink /D "%target%%%~pnA" "%%~fA"
)

Open in new window



I have folders:

C:\Alpha
C:\Beta
C:\Charlie

Each folder has data in.

After running the above script I am expecting to see symbolic links appearing in the C:\Downloads\Symlink folder but I get a 'cannot find the path' error.  This is now a step in the right direction but also confusing.  If I manually create a C:\Downloads\Symlink\Alpha folder the script then works perfectly for the Beta and Charlie folders and create the symbolic links.  However the Alpha folder is just the folder I manually created.  So the script is working when I manually create the first folder?!
0
 
robclarke41Author Commented:
Must be me I tried it again and it's working! Thanks guys, you are legends!
0
 
Steve KnightIT ConsultancyCommented:
No problem, glad we got there!
0
 
robclarke41Author Commented:
Sorry guys one more question! The script works great for the range I wanted but how would I get the script to just include all files and folders in a directory?
0
 
Steve KnightIT ConsultancyCommented:
I would say create a link to the dir above? Do you mean a link to each file individually?
0
 
robclarke41Author Commented:
Sorry no just a link to every folder in a directory. Like above but just a way of including everything rather than specifying a range?
0
 
Steve KnightIT ConsultancyCommented:
You should be able to use my original script for that, on phone at no. But think was second one.
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 11
  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now