Jump to content

For loop problem


Recommended Posts

Hi,

I have a CMD file which extracts users from an Active Directory group then trims it so only the username is displayed in the output file GroupMemberTrim.txt.

It works fine, however I would like to use dynamic file names instead of static

GroupMemberExtract.txt -> %groupname%-Extract.txt

GroupMemberTrim.txt -> %groupname%-Trim.txt

When I change this it breaks the FOR loop so the %%a variable does not read in the contents of %groupname%-Extract.txt instead it reads the filename %groupname%-Extract.txt as the %%a variable.

Does anyone have any ideas how this could be fixed?

Thanks :)


@echo off
CLS

:GroupsMembersExtract
echo.
set /p groupname=enter groupname:
echo.
echo.
dsquery * domainroot -filter "(&(objectClass=group)(name=""%groupname%""))" -l -d DomainName -attr member >>GroupMemberExtract.txt


:GroupsMembersTrim
CLS
setlocal enabledelayedexpansion
FOR /F "tokens=1 delims=," %%a IN ( GroupMemberExtract.txt ) DO (
set oldName=%%a
set newName=!oldName:~3!
echo !%newName!>>GroupMemberTrim.txt
)
SETLOCAL DISABLEEXTENSIONS


:END

Link to comment
Share on other sites


Does anyone have any ideas how this could be fixed?

Yes.

http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/questions-with-yes-or-no-answers.html

I am not sure to have understood the issue (actually I am sure to have it not understood) :ph34r:

Please post the .cmd that work and the one that doesn't and an example of the file to be parsed (GroupMemberExtract.txt).

What is this?:

!%newName!

jaclaz

Link to comment
Share on other sites

Hi Jaclaz, thanks for the reply

Sorry !%newName! was a typo, it should be !newName!

Ok here is the information you asked for.

When the CMD file prompts for input at the line

set /p groupname=enter groupname:

I am entering Accounts

Working CMD file


@echo off
CLS

echo.
set /p groupname=enter groupname:
echo.
echo.
dsquery * domainroot -filter "(&(objectClass=group)(name=""%groupname%""))" -l -d DomainName -attr member >>GroupMemberExtract.txt

CLS
setlocal enabledelayedexpansion
FOR /F "tokens=1 delims=," %%a IN ( GroupMemberExtract.txt ) DO (
set oldName=%%a
set newName=!oldName:~3!
echo !newName!>>GroupMemberTrim.txt
)
SETLOCAL DISABLEEXTENSIONS

:END

GroupMemberExtract.txt

CN=Joe Bloggs,OU=Accounts,OU=User Accounts,DC=DomainName,DC=company,DC=co,DC=uk

GroupMemberTrim.txt

Joe Bloggs

Non working CMD file with vairables

@echo off
CLS

echo.
set /p groupname=enter groupname:
echo.
echo.
dsquery * domainroot -filter "(&(objectClass=group)(name=""%groupname%""))" -l -d DomainName -attr member >>"%groupname%Extract.txt"

CLS
setlocal enabledelayedexpansion
FOR /F "tokens=1 delims=," %%a IN ( "%groupname%Extract.txt" ) DO (
set oldName=%%a
set newName=!oldName:~3!
echo !newName!>>"%groupname%Trim.txt"
)
SETLOCAL DISABLEEXTENSIONS

:END

AccountsExtract.txt

CN=Joe Bloggs,OU=Accounts,OU=User Accounts,DC=DomainName,DC=company,DC=co,DC=uk

AccountsTrim.txt

AccountsExtract.txt

So as you see, using the variables in this example throws out the %%a in the for loop and instead of phrasing the contents it uses the filename.

Link to comment
Share on other sites

Before looking at the latter script I'd suggest you start by 'improving' the first one.

Get rid of everything below the DSQUERY line and replace it with something like this:

FOR /F "TOKENS=2 DELIMS==," %%# IN (
'FINDSTR/B "CN=" GroupMemberExtract.txt') DO ECHO=%%#>>GroupMemberTrim.txt

<EDIT />

You will then see your problem which was caused by the inclusion of double quotes around the file name will have gone.

FOR /F "TOKENS=2 DELIMS==," %%# IN (
'FINDSTR/B "CN=" "GroupMemberExtract.txt"') DO ECHO=%%#>>GroupMemberTrim.txt

Edited by Yzöwl
see <EDIT />
Link to comment
Share on other sites

So as you see, using the variables in this example throws out the %%a in the for loop and instead of phrasing the contents it uses the filename.

Yes/No.

The contents of AccountsTrim.txt after the:

set oldName=%%a
set newName=!oldName:~3!

should be:

ountsExtract.txt

But as Yzöwl posted it is easier/better to change the actual code/method.

If I get it right, you are using the for loop to "post process" the "integral" output of the dsquery command, you should be able to directly go to "GroupMemberTrim.txt" without having to pass through the "GroupMemberExtract.txt".

There might be the need to add more than a efw ESCAPE characters but including the:

dsquery * domainroot -filter "(&(objectClass=group)(name=""%groupname%""))" -l -d DomainName -attr member

inside a for loop seems to me like possible and "better".

Let's say that (once having the special character being escaped properly) the above code is just "%Command%"

FOR /F "tokens=2 delims=,=" %%A IN ('%Command%') DO ECHO %%A

it should work, see this as an example (working for me):

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
ECHO CN=Joe Bloggs,OU=Accounts,OU=User Accounts,DC=DomainName,DC=company,DC=co,DC=uk>test.txt
TYPE test.txt
FOR /F "tokens=2 delims=,=" %%A IN ('TYPE test.txt') DO ECHO %%A
SET dsquery=CN=Joe Bloggs,OU=Accounts,OU=User Accounts,DC=DomainName,DC=company,DC=co,DC=uk>test.txt
FOR /F "tokens=3 delims=,=" %%A IN ('SET dsquery') DO ECHO %%A

jaclaz

Link to comment
Share on other sites

Just to prevent you getting confused with all of the suggestions for changing things, I'd just like to show you the difference betweeen your working and non working scripts.

FOR /F "tokens=1 delims=," %%a IN ( GroupMemberExtract.txt ) DO (

FOR /F "tokens=1 delims=," %%a IN ( "%groupname%Extract.txt" ) DO (

The former is looking at a file whilst the latter is looking at a string.
FOR /F ["options"] %%variable IN (file-set) DO command [command-parameters]

FOR /F ["options"] %%variable IN ("string") DO command [command-parameters]

This means that your non working script was parsing the string AccountsExtract.txt not the content of a file named AccountsExtract.txt.

The result you should have seen as jaclaz pointed out above should have been ountsExtract.txt and not that which you posted and therefore potentially prevented others from solving your issue.

Link to comment
Share on other sites

Thanks jaclaz & Yzöwl

OK that makes sense now.

I cant test it at the moment, will do it tomorrow. My only concern would be that %groupname% in some cases will contain spaces. I think omitting the " " will cause a problem. I will report what I find. :)

FOR /F "tokens=1 delims=," %%a IN ( "%groupname%Extract.txt" ) DO (
Link to comment
Share on other sites

I wouldn't do that task like this because:

- the way you do it, if groups are members of the group you're trying to get members, you won't see the users members of those groups.

- if the DN (you're parsing it in your script) doesn't contain the same "display name", you might end up getting wrong accounts. Usually i prefer extracting the samid or samaccountname (login for a user account) as they are unique and they can't contain space or special character.

- for the same reason, i replaced a query on the samid of the group instead of its name.


@echo off
CLS

echo.
set /p groupname=enter groupname:

dsquery group -samid %groupname% |dsget group -members -expand |dsget user -display >%groupname%Extract.txt

Depend on your task, you might prefer using adfind as it is a lot more powerful and can format properly the output.

Link to comment
Share on other sites

Thanks jaclaz & Yzöwl

OK that makes sense now.

I cant test it at the moment, will do it tomorrow. My only concern would be that %groupname% in some cases will contain spaces. I think omitting the " " will cause a problem. I will report what I find. :)

FOR /F "tokens=1 delims=," %%a IN ( "%groupname%Extract.txt" ) DO (

For such a scenario you could try:

FOR /F "USEBACKQ TOKENS=2 DELIMS==," %%# IN ("%groupname%Extract.txt") DO ECHO=%%#>>"%groupname%Trim.txt"

I would also suggest you use DSQUERY GROUP piping the results through DSGET as suggested above by allen2, it may seem a little OTT for you but it was the first approach I considered when I saw your initial post.

Link to comment
Share on other sites

Thanks everyone I have it working the way I need it now.

@allen2 - thats a fair point and a good one to look out for. However in this environment there are no nested groups and all usernames are generated from another system so should be fine with the current task.

@Yzöwl - I have used the line you provided, thanks very much :)

FOR /F "USEBACKQ TOKENS=2 DELIMS==," %%# IN ("%groupname%Extract.txt") DO ECHO=%%#>>"%groupname%Trim.txt"

I will take a look at the other methods tools mentioned, but I can get what I need for now!

Cheers

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...