# Solved: batch file using NET SHARE - parsing issues



## geriatric (Aug 26, 2003)

Hello.

I have been hammering away at a particular problem for awhile now, off and on. I am tired of windows 7 ridiculous network sharing scheme. Give me good old XP style, insecure and easy to use. lol.

Anyway, what I am doing is, via a context menu, calling a batch file, with two parameters. %1 is a command, such as "share", and %2 is the path (context menu is always passing an FQP, on a directory).

When the batch script gets the parameter to create a share, it will:
1. check the target exists
2. concatenate a target directory with underscores (ie. some path will become some_path)
3. prepend a user supplied value (ie. temp_ prepended like temp_some_path)
4. use net share to create the share with /grant:everyone,full (exactly what the OS does)
5. use icacls to grant everyone RX rights with OICI inheritance (exactly as the OS does)
(note this is all about simple file sharing for the home, no security required really behind the router)

The batch script will also reverse this process, but I originally built it to delete ALL of these shares, because the idea WAS to use it at LAN parties, so ALL the shares were really temporary anyway. So the batch file would:
1. use a for loop, look for any share name with the prepend tag (ie. temp_ )
2. ignore anything without the prepend tag implicitly
3. use net share with /del parameter
4. use icacls with /remove:g everyone

It works fine enough. However, I became fed up with the "new and improved" windows 7 sharing, tweaked a few things so that no credential prompts come up when sharing, at all, and now want to rid myself of the "share with" context menu and create my own. Not hard.

However, the hard part is being choosy about what to stop sharing.

The NET SHARE command will return a (I think) tab delimited output of share names to FQP. I want the option of simply sharing a directory with the same name as the directory, which might contain spaces (although I rarely use spaces, it happens when you get lazy  ). So my For loop will never know how many tokens to use, thus I can't know how many to expect.

Here is a snippet of the batch file

```
@ECHO OFF
SETLOCAL EnableDelayedExpansion

SET _prepend=temp_
SET _alen=5

IF /I [%1]==[unshare] GOTO :xunshare
IF /I [%1]==[share] GOTO :xshare
IF /I [%1]==[add_rights] GOTO :xadd_rights
IF /I [%1]==[rem_rights] GOTO :xrem_rights
GOTO :bye

:xunshare
FOR /F "skip=4" %%I IN ('NET SHARE') DO (
	SET Share=%%I
	SET var=!Share:~0,%_alen%!
	IF !var!==!_append! NET SHARE !Share! /del
)
GOTO :bye

:xshare
IF /I [%2]==[] GOTO :bye
IF NOT EXIST %2 GOTO :bye
FOR /D %%I IN (%2) DO (
	SET Share=%%~nxI
	SET Share=!Share: =_!
	NET SHARE !_prepend!!Share!=%2 /GRANT:Everyone,Full
)
GOTO :bye
```
So, what I am trying to do is parse the output of NET SHARE, and return the SHARE NAME for each share listed. This I will then match against the %2 parameter which I will have to parse out to find the directory, and if they match can delete the share using net share. I could of course write this in a number of languages, or create a full blown app, but what fun is that lol?

So I need help on how I can parse the NET SHARE results out.

For example, suppose the NET SHARE output was something like this:

```
my test dir 2     c:\my test dir\test_dir\my test dir 2
some_dir                   c:\my test dir\some_dir
```
You can see my output will vary in structure. I understand a lot of the commands, but this one I am struggling with.

Is there any batch geeks who might like to try and help me with this?

Any help appreciated.

geri.

btw, been messing with permutations of this, trying to come up with something that works. Very messy and very verbose lol

```
@echo off
SetLocal EnableDelayedExpansion
for /f "skip=4 tokens=*" %%a in ('net share') DO SET M=!M!%%a:::

ECHO %M%


for /f "skip=4 tokens=2,3 delims= " %%a in ('net use ^| FIND /I "%1"') do (
	echo share b.. %%b
   Set SHARE=%%b
   echo cho shar.. !SHARE!
   Set SHARE=!SHARE:%1=%2!
   echo cho shar end.. !SHARE!

)
echo cho =================

For /F "skip=4 delims=<tab>" %%I IN ('net share') do (
	set m=!m!%%I_
	echo !m!
)

for /F "skip=4 tokens=* delims=*" %%I in ('net share') do (
	echo I is ________ %%I
	echo j is %%J
  REM ~ set share=%%i
  echo cho nxi .. %%~nxI
  echo cho nxj--....  %%~nxJ
  REM ~ echo cho XXX.. %%~dp$PATH:I
  REM ~ echo choZZZZ %%~ftzaI
  SET fat=%%I
  SET fat=!fat: =.!
  echo fat is now !fat!
  SET Var=%%~nxI
  echo cho var now.. !Var!
  REM ~ SET share=%%~nxI
  SET Var=!Var: =_!

  REM ~ SET var=!Share:~0,%_alen%!
  echo this is.. !Var!

)
```


----------



## geriatric (Aug 26, 2003)

I got it to work, but its long and complicated because I don't know all the right tricks of the trade yet lol.

It steps through the output of net share, cleaning up the whitespace, to find all the share names. It then compares the found names to the input parameter, and removes the share.

Maybe there is some kind soul who would care to teach an oaf like myself how to stream-line this. If not, maybe someone along the way can get something useful out of it.


```
:unshare
:: stop sharing specific shared directories
IF /I [%2]==[] GOTO :bye
IF NOT EXIST %2 GOTO :bye
FOR /D %%I IN (%2) DO SET sname=%%~nxI

FOR /F "skip=4 tokens=1,2 delims=:" %%I IN ('net share') DO (
	SET xshare=%%I
	SET xpath=%%J
	IF DEFINED xpath (
		SET xshare=!xshare:~0,-1!
		FOR /L %%Q IN (1,1,100) DO IF "!xshare:~-1!"==" " SET xshare=!xshare:~0,-1!
		IF "!xshare!" EQU "" (
			REM ~ do nothing
		) ELSE (
			IF "!xshare!" EQU "The command completed successfully." (
				REM ~ do nothing
			) ELSE (
				IF /I "!xshare!" EQU "!sname!" (
					NET SHARE "!xshare!" /del
					GOTO :xrem_rights
					GOTO :bye
				) ELSE (
					REM ~ do nothing
				)
			)
		)
	) ELSE (
		FOR /L %%Q IN (1,1,100) DO IF "!xshare:~-1!"==" " SET xshare=!xshare:~0,-1!
		IF "!xshare!" EQU "" (
			REM ~ do nothing
		) ELSE (
			IF "!xshare!" EQU "The command completed successfully." (
				REM ~ do nothing
			) ELSE (
				IF /I "!xshare!" EQU "!sname!" (
					NET SHARE "!xshare!" /del
					GOTO :xrem_rights
					GOTO :bye
				) ELSE (
					REM ~ do nothing
				)
			)
		)
	)
)
GOTO :bye
```
geri.


----------



## foxidrive (Oct 20, 2012)

You don't specify what the input data is.

if it is a sharename to remove then you can test for it's existence and just remove it if it is found:


```
net share |findstr /i /c:"%~1">nul && net share "%~1" /del
```


----------



## geriatric (Aug 26, 2003)

My apologies, I thought in my first thread this might explain it


foxidrive said:


> Anyway, what I am doing is, via a context menu, calling a batch file, with two parameters. %1 is a command, such as "share", and %2 is the path (context menu is always passing an FQP, on a directory).


but then, walls of text like mine usually are don't help 

Yes, then, the input is a FQP, already quoted, from context menu command. This is a, umm, short piece of code you present lol. Lets see if I follow it, as I haven't ran it yet.


```
net share |findstr /i /c:"%~1">nul && net share "%~1" /del
```
net share is piped to findstr.
findstr is looking for %1 with no case sense and using literal string, output to nul
the double & is going to process to the right if the left produces errorlevel 0?
so the logic flow is that findstr searches the resulting output (aka findstr's input) of net share, and it is findstr that returns a 0 errorlevel? or does redirecting to nul produce the errorlevel? I understand I think what the logic is, I don't however understand how you decided to use the && - that is, how you know what errorlevel to expect when piping and redirecting like that. Can you explain that part at all?

How can I catch this if I wanted to, as success or failure? When you do multiple commands on one line, is it always the last command that you trap the errorlevel for?

Also, is the use of "%~1" meant to remove any quotes if they exist, but then ensure they are present if needed? So if the registry command was: batchfile.bat "%1", that command will strip my quotes, making sure to replace them, but if there were no quotes, it does nothing and still encloses?

One more thing. Have you ran this at all? I will in a bit here, but when I tried using findstr with the output of net share, it hangs on win7. This appears to be the behaviour of findstr if there is no crlf? It did this multiple times when I tested it, so I used find instead. I will give this a go later today when I have time to work on it and see what happens.

Thanks for taking the time to reply. Much appreciated. Sorry for so many additional questions, but I like to understand things.

geri.


----------



## foxidrive (Oct 20, 2012)

geriatric said:


> findstr is looking for %1 with no case sense and using literal string, output to nul
> the double & is going to process to the right if the left produces errorlevel 0?
> 
> Yes. Findstr and find both return errorlevel zero if the text is found. The redirection to NUL doesn't change the errorlevel.
> ...




This might work: and the %~nx1 will return the share name, if it assumed to be the same as the folder name.


```
net share |find /i "%~1">nul && (net share "%~nx1" /del || echo share deletion failed && echo share deleted successfully)
```


----------



## geriatric (Aug 26, 2003)

Your first idea appears to work using findstr. Here is what I used

```
net share |findstr /i /c:"%~1">nul && (net share "%~1" /del || echo share deletion failed && echo share deleted successfully)
```
The output of net share when piped into findstr likely has a crlf at the end of the total output. I was using it in a FOR /F loop, so each "line" likely had no termination. It sounds like the case anyway.

I like the idea of using "%~nx1" to get the drive letter out of the equation. However, wouldn't "%~n1" be better, as we are dealing explicitly with containers and not objects? Is there a caveat I am not aware of that one would want to use nx1 instead of n1?

My code looks too much like script languages I think. I don't make good use of piping and redirection. Replies like yours offer a lot of valuable ideas. Thanks!!

geri.

EDIT: I found out that when using net share <sharename> /del, that you can use a FQP so you don't need the actual share name as represented. I did not know that, and makes the whole thing much easier! Again, thanks for spurring the creative juices!


----------



## foxidrive (Oct 20, 2012)

geriatric said:


> I like the idea of using "%~nx1" to get the drive letter out of the equation. However, wouldn't "%~n1" be better, as we are dealing explicitly with containers and not objects? Is there a caveat I am not aware of that one would want to use nx1 instead of n1?
> 
> If the folder has a period in it at all it will be treated like an extension and %~n will break it. With the x added then it will always work correctly (exceptions are with % ^ and ! characters, at different times)
> 
> EDIT: I found out that when using net share <sharename> /del, that you can use a FQP so you don't need the actual share name as represented. I did not know that, and makes the whole thing much easier! Again, thanks for spurring the creative juices!


beauty! I didn't know that and am happy to learn it too.

Cheers


----------



## geriatric (Aug 26, 2003)

That one-liner is awesome. Replaced 3 pieces with that one. Very nice.

I am afraid though, I am still struggling with my original issue.

If we suppose that the NET SHARE output looks like this

```
Share name   Resource                        Remark

-------------------------------------------------------------------------------
_temp_Control_Panel_Client
             C:\Program Files\NVIDIA Corporation\Control Panel Client

purple place C:\Program Files\Microsoft Games\Purble Place\en-US

test dir f   F:\test dir f
test share 2 C:\test share\test share 2
The command completed successfully.
```
we can see that one share is actually in two lines.

The shares are created by the batch script in two ways. One is with the line provided by foxidrive, passing the FQP to the script, and the share is made exactly as the directory is, spaces included. Removing these shares is easy also, thanks again to foxidrive, as I used his/her idea to remove the share too.

The other way shares are created is to replace all spaces with underscores, and prepend a marker to the name. For example, the directory "c:\program files\microsoft games\purble place" would be shared AS _temp_Purble_Place (where _prepend would be a unique marker, like _temp_ ). This gives me a way to easily find any share with the prepend value of _temp_ and remove the shares with something simple like this (where _alen is the length of the _prepend value)

```
FOR /F "skip=4" %%I IN ('NET SHARE') DO (
	SET Share=%%I
	SET var=!Share:~0,%_len%!
	IF "!var!"=="!_prepend!" (
		NET SHARE !Share! /del
		REM ~ CALL :rem_loop
	)
)
```
This is easy enough, as I can extract the _prepend value and find matches easily. This works because the resulting output of the loop is always going to be the first token, and when the share name has no spaces, it will always be the full share name (or at least something I can check on). So I pull the first X number of characters, see if they match my marker, and if so, remove the share.

However, note the CALL I am trying to do. The purpose of this call is to use ICACLS on each share that was removed, to also remove the DACL rights of everyone that was assigned earlier by the script.

The problem lies in that the FOR loop will return only the share name, or only the path of the share, or sometimes even the share name and path may contain whitespace. You can see in my second reply that long FOR loop gets rid of whitespace and successfully removes the share. It then calls the ICACLS function to remove the rights based on the input (aka %2 in this case, which is the FQP to the directory being worked on).

I know, a lot of text here, but I don't know how to describe it without details. I am sure I can hack up a nice long FOR loop, but is there some way to do this that is less confusing, and maybe cleaner?

To sum it up:
I need a way to step through the net share output, gathering both the share name and the FQP of the share. Any whitespace needs to be removed. Then I can use (as we found out) just the FQP to remove the share and also remove the rights using ICACLS.

Thank you again for anyone willing to help.

geri.


----------



## geriatric (Aug 26, 2003)

I think I solved it.

Assume that a directory is shared, such as
C:\Program Files\NVIDIA Corporation\Control Panel Client
and assume that it was shared AS _temp_Control_Panel_Client

Now assume that you had multiple shares using _temp_ in the naming structure, and that you wanted to remove all of these "_temp_" shares at one time. You might not be able to use NET SHARE to do this because the output of it might look like this:

```
Share name   Resource                        Remark

-------------------------------------------------------------------------------
_temp_Control_Panel_Client
             C:\Program Files\NVIDIA Corporation\Control Panel Client

_temp_Uninstall
             C:\Program Files\NVIDIA Corporation\Uninstall

purple place C:\Program Files\Microsoft Games\Purble Place\en-US

test dir f   F:\test dir f
test share 2 C:\test share\test share 2
The command completed successfully.
```
As you can see, for some reason the share name and the share path are not on the same line. It can be done, but is overly complicated. Instead, you can do a reg query to find all the current shares, and parse the result out, looking for the _temp_ value. Something like this:

```
@ECHO OFF
SETLOCAL EnableDelayedExpansion

SET vRegQuery=reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares /t REG_MULTI_SZ /se #
FOR /F "skip=2 tokens=*" %%S IN ('%vRegQuery%') DO (
	ECHO %%S | FINDSTR /I /B /C:"_temp_">NUL && (
	FOR /F "tokens=3,5 delims=#" %%H IN ('ECHO "%%S"') DO (
		set ll=%%H&set ll=!ll:~5!&echo !ll! - the full path, can do something with it
		set jj=%%I&set jj=!jj:~10!&echo !jj! - the share name, can do something with it
		)
	)
)

EXIT
```
The result is all share names that have the _temp_ at the beginning of the name, and the FQP to the share. Now you can call NET SHARE <FQP> /del and remove all those shares. If, as in my case, you also need to call ICACLS, you have the FQP, not just the share name.

Maybe there is a better way to do this? I am always open to being taught new tricks 

One other thing I found (new to me anyway) was that when FINDSTR gets stuck in situations where there is no crlf at the end, you can enter one yourself, or just use it to format your output on multiple lines rather than one. The trick is to assign the carat to a variable, and then leave two blank lines before any other syntax. You must also use EnableDelayedExpansion. Something like this:

```
@ECHO OFF
SETLOCAL EnableDelayedExpansion
SET LF=^


:: the two blank lines are needed for LF to become a linefeed with !LF!

:: first show how variable grows on one line
SET lin1=this is line one, or first part of output
SET lin1=!lin1!this is line two, or additional part of output
ECHO !lin1!

:: using the LF variable, you could do this
SET lin1=this is line one, or first part of output
SET lin1=!lin1!!LF!this is line two, or additional part of output
ECHO !lin1!
```
geri.


----------



## foxidrive (Oct 20, 2012)

I'm glad you have a solution. 

I had only come up with shareEnum by Microsoft PStools (and Softperfect Network Scanner) which can export a list of sharenames and FQP in quoted format, but it's a GUI tool and you'd have to use sendkeys of similar to get a batch file to export the data. Querying the registry seems like a better plan.


----------

