# Solved: cannot get proper syntax for FINDSTR



## ttx336 (Nov 7, 2012)

I am trying to setup a command script that will check to see if the filename begins with 2 numbers and a space, such as:

01 Title Of Song One.mp3

then, if it does, strip the first three characters to produce:

Title Of Song One.mp3

Here is what I have tried so far, I'd be embarrassed to say how much time I've put into this, lol...


```
@echo off

pushd "M:\iTunes\Music"
for /f "delims=" %%z in ('dir /b /ad') do (
pushd "%%z"
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
popd
GOTO:EOF

:next
set fname=%~nx1
Findstr /c:"[0-9][0-9] *" "%fname%"
	if %ERRORLEVEL% EQU 0 echo I found a number
set name=%~nx1
set name=%name:~3%
echo ren "%~nx1" "%name%"
popd
pause
```
I think I have the mainstay of it working, I have tested the latter part that does the stripping separately, I just cannot get the syntax correct for FINDSTR... here is what it outputs currently...


```
D:\Dropbox\Computers\Batch>strippit

D:\Dropbox\Computers\Batch>&#8745;&#9559;&#9488;@echo off
'&#8745;&#9559;&#9488;@echo' is not recognized as an internal or external command,
operable program or batch file.

D:\Dropbox\Computers\Batch>pushd "M:\iTunes\Music"

M:\iTunes\Music>for /F "delims=" %z in ('dir /b /ad') do (
pushd "%z"
 for /F "delims=" %a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%a"
)

M:\iTunes\Music>(
pushd "38 Special"
 for /F "delims=" %a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%a"
)

M:\iTunes\Music\38 Special>call :next "M:\iTunes\Music\38 Special\The Very Best
of the A&M Years (1977-198\50 Hold on Loosely.mp3"

M:\iTunes\Music\38 Special>set fname=50 Hold on Loosely.mp3

M:\iTunes\Music\38 Special>Findstr /c:"[0-9][0-9] *" "50 Hold on Loosely.mp3"
FINDSTR: Cannot open 50 Hold on Loosely.mp3

M:\iTunes\Music\38 Special>if 1 EQU 0 echo I found a number

M:\iTunes\Music\38 Special>set name=50 Hold on Loosely.mp3

M:\iTunes\Music\38 Special>set name=Hold on Loosely.mp3

M:\iTunes\Music\38 Special>echo ren "50 Hold on Loosely.mp3" "Hold on Loosely.mp3
3"
ren "50 Hold on Loosely.mp3" "Hold on Loosely.mp3"

M:\iTunes\Music\38 Special>popd

M:\iTunes\Music>pause
```
Where I am hung up is: FINDSTR: Cannot open 50 Hold on Loosely.mp3

I've tried removing the quotes from %fname% but then it parses the string, I have tried all kinds of combinations of the /R /C:, etc...

I really do suck at this! but it is fun and challenging...

Thanks in advance,
-Gary


----------



## foxidrive (Oct 20, 2012)

Try this. The quotes are necessary for poison characters and so the leading . in the findstr term eats the first quote.


```
@echo off
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:".[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0 echo I found a number
pause
```


----------



## ttx336 (Nov 7, 2012)

I put this together with my earlier framework and pointed it to the microSD that is currently G:\
I replaced the . with ^ in

echo."%fname%"|findstr /r /c:".[0-9][0-9] .*" >nul

because I discovered that there are a large group of files that are named something like this:

1-01 Song One.mp3
1-02 Song Two.mp3

and it was picking up on them since if I understand it correctly the . is a wildcard for "any character"

so now I have:


```
:: striptest.cmd

@echo off

pushd "G:\"
for /f "delims=" %%z in ('dir /b /ad') do (
pushd "%%z"
echo *****
echo Current directory is: %%z
echo *****
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
popd
)
popd
GOTO:EOF

:next
echo set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0 echo Found It!
```
hoping that it would limit it to the filenames that begin with the sequence "number,number,space" but now, it won't match anything.

Here is the output from striptest.cmd:


```
D:\Batch>striptest
*****
Current directory is: 38 Special
*****
set "fname=50 Hold on Loosely.mp3"
set "fname=53 Caught Up in You.mp3"
*****
Current directory is: A Fine Frenzy
*****
set "fname=06 Almost Lover.m4a"
*****
Current directory is: a-ha
*****
set "fname=49 Take On Me.mp3"
set "fname=14 Take On Me.m4a"
*****
Current directory is: Abba
*****
set "fname=01 Dancing Queen.mp3"
set "fname=02 Knowing Me, Knowing You.mp3"
set "fname=03 Take A Chance On Me.mp3"
set "fname=17 The Name Of The Game.mp3"
set "fname=19 Waterloo.mp3"
*****
Current directory is: Ace of Base
*****
set "fname=02 The Sign.mp3"
*****
Current directory is: ADELE
*****
^CTerminate batch job (Y/N)? y
```
Also, I tried this, I added the logic in the "IF" statement to handle the renaming upon a match (this one does not have the . (dot) nor does it have the ^ (carat):


```
:: strippit.cmd

@echo off

pushd "G:\"
for /f "delims=" %%z in ('dir /b /ad') do (
pushd "%%z"
echo *****
echo Current directory is: %%z
echo *****
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
popd
)
popd
GOTO:EOF

:next
echo set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0 (
set "name=%~nx1"
set name=%name:~3%
echo ren "%~nx1" "%name%"
)
```
here is the output from strippit.cmd


```
D:\Batch>strippit
*****
Current directory is: 38 Special
*****
set "fname=50 Hold on Loosely.mp3"
ren "50 Hold on Loosely.mp3" "~3"
set "fname=53 Caught Up in You.mp3"
ren "53 Caught Up in You.mp3" ""
*****
Current directory is: A Fine Frenzy
*****
set "fname=06 Almost Lover.m4a"
ren "06 Almost Lover.m4a" "~3"
*****
Current directory is: a-ha
*****
set "fname=49 Take On Me.mp3"
ren "49 Take On Me.mp3" ""
set "fname=14 Take On Me.m4a"
ren "14 Take On Me.m4a" "~3"
*****
Current directory is: Abba
*****
set "fname=01 Dancing Queen.mp3"
ren "01 Dancing Queen.mp3" ""
set "fname=02 Knowing Me, Knowing You.mp3"
ren "02 Knowing Me, Knowing You.mp3" "~3"
set "fname=03 Take A Chance On Me.mp3"
ren "03 Take A Chance On Me.mp3" ""
set "fname=17 The Name Of The Game.mp3"
ren "17 The Name Of The Game.mp3" "~3"
set "fname=19 Waterloo.mp3"
ren "19 Waterloo.mp3" ""
*****
Current directory is: Ace of Base
*****
set "fname=02 The Sign.mp3"
ren "02 The Sign.mp3" "~3"
*****
Current directory is: ADELE
*****
set "fname=01 Daydreamer.m4a"
ren "01 Daydreamer.m4a" ""
set "fname=02 Best for Last.m4a"
ren "02 Best for Last.m4a" "~3"
set "fname=03 Chasing Pavements.m4a"
ren "03 Chasing Pavements.m4a" ""
set "fname=04 Cold Shoulder.m4a"
ren "04 Cold Shoulder.m4a" "~3"
set "fname=05 Crazy for You.m4a"
Terminate batch job (Y/N)? y
```
so for some reason the "IF" statement is throwing off the "set name=%name:~3" or so it seems...

although the "name=%~nx1" appears to be loading correctly... perhaps I am not doing it in such a way that creates a string perhaps? and that prevents the string manipulator ~3 from being correctly interpreted?

I see that the output is something like:

set "fname=01 Daydreamer.m4a"
ren "01 Daydreamer.m4a" ""
set "fname=02 Best for Last.m4a"
ren "02 Best for Last.m4a" "~3"

and it wants to rename the file to either "" (a null string?) or "~3"

Thanks in advance,
-Gary


----------



## foxidrive (Oct 20, 2012)

ttx336 said:


> I put this together with my earlier framework and pointed it to the microSD that is currently G:\
> I replaced the . with ^ in
> 
> echo."%fname%"|findstr /r /c:".[0-9][0-9] .*" >nul
> ...


That's not the way it works. The first character in the line is always a " and the first . in the regexp will always be used to match the " 
You can use the ^ as well to anchor the string to the start - I missed that.

echo."%fname%"|findstr /r /c:"^.[0-9][0-9] .*" >nul

BTW, the . in echo. is not necessary here but it is not part of the string either.

If you have other issues once you solve this part, then reply again.


----------



## ttx336 (Nov 7, 2012)

foxidrive said:


> If you have other issues once you solve this part, then reply again.


...and of course, I do... I have the control working, I cannot get the variable called "name" to set properly, it seems to always have the previous filename... I only ran it against two files because the output gets pretty huge with even 4 files but here is the output:


```
D:\Batch>test

D:\Batch>for /F "delims=" %a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%a
"

D:\Batch>call :next "D:\Batch\06 Penthouse Pauper.mp3"

D:\Batch>set "fname=06 Penthouse Pauper.mp3"

D:\Batch>echo."06 Penthouse Pauper.mp3" | findstr /r /c:"^.[0-9]-[0-9][0-9] .*"
 1>nul

D:\Batch>if 1 EQU 0 (
echo I found a number in 06 Penthouse Pauper.mp3
 echo this is fname: "06 Penthouse Pauper.mp3"
 echo set "name=06 Penthouse Pauper.mp3"
 echo this  is name: "Green River.mp3"
 echo set "name=nthouse Pauper.mp3"
 echo ren "06 Penthouse Pauper.mp3" "Green River.mp3"
 echo why the previous filename??!!         Green River.mp3
)

D:\Batch>echo."06 Penthouse Pauper.mp3" | findstr /r /c:"^.[0-9][0-9] .*"  1>nul


D:\Batch>if 0 EQU 0 (
echo I found a number in 06 Penthouse Pauper.mp3
 echo this is fname: "06 Penthouse Pauper.mp3"
 echo set "name=06 Penthouse Pauper.mp3"
 echo this  is name: "Green River.mp3"
 echo set "name=Penthouse Pauper.mp3"
 echo ren "06 Penthouse Pauper.mp3" "Green River.mp3"
 echo why the previous filename??!!         Green River.mp3
)
I found a number in 06 Penthouse Pauper.mp3
this is fname: "06 Penthouse Pauper.mp3"
set "name=06 Penthouse Pauper.mp3"
this  is name: "Green River.mp3"
set "name=Penthouse Pauper.mp3"
ren "06 Penthouse Pauper.mp3" "Green River.mp3"
why the previous filename??!!         Green River.mp3

D:\Batch>call :next "D:\Batch\1-01 Green River.mp3"

D:\Batch>set "fname=1-01 Green River.mp3"

D:\Batch>echo."1-01 Green River.mp3" | findstr /r /c:"^.[0-9]-[0-9][0-9] .*"  1>
nul

D:\Batch>if 0 EQU 0 (
echo I found a number in 1-01 Green River.mp3
 echo this is fname: "1-01 Green River.mp3"
 echo set "name=1-01 Green River.mp3"
 echo this  is name: "Green River.mp3"
 echo set "name=Green River.mp3"
 echo ren "1-01 Green River.mp3" "Green River.mp3"
 echo why the previous filename??!!         Green River.mp3
)
I found a number in 1-01 Green River.mp3
this is fname: "1-01 Green River.mp3"
set "name=1-01 Green River.mp3"
this  is name: "Green River.mp3"
set "name=Green River.mp3"
ren "1-01 Green River.mp3" "Green River.mp3"
why the previous filename??!!         Green River.mp3

D:\Batch>echo."1-01 Green River.mp3" | findstr /r /c:"^.[0-9][0-9] .*"  1>nul

D:\Batch>if 1 EQU 0 (
echo I found a number in 1-01 Green River.mp3
 echo this is fname: "1-01 Green River.mp3"
 echo set "name=1-01 Green River.mp3"
 echo this  is name: "Green River.mp3"
 echo set "name=1 Green River.mp3"
 echo ren "1-01 Green River.mp3" "Green River.mp3"
 echo why the previous filename??!!         Green River.mp3
)

D:\Batch>GOTO:EOF

D:\Batch>
```
so you can see that it is properly identifying files that start with "number,number,space" and differentiating those from "number,dash,number,number,space"

and here is the command script as it stands (with extraneous testing echoes, etc):


```
:: Test.cmd
:: gettin another butt kickin
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
GOTO:EOF

:next
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^.[0-9]-[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0	(


echo I found a number in %fname%
echo this is fname: "%fname%"
echo set "name=%~nx1%"
echo this  is name: "%name%"
echo set "name=%fname:~5%"
echo ren "%fname%" "%name%"
echo why the previous filename??!!         %name%
)

echo."%fname%"|findstr /r /c:"^.[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0	(

echo I found a number in %fname%
echo this is fname: "%fname%"
echo set "name=%~nx1%"
echo this  is name: "%name%"
echo set "name=%fname:~3%"
echo ren "%fname%" "%name%"
echo why the previous filename??!!         %name%
)
```
I'm very sorry that I am too dense to figure this out on my own!

Thanks again,
-Gary


----------



## Squashman (Apr 4, 2003)

You are manipulating a variable inside a code block. Remember from a previous thread we had talked about the use of delayed expansion.


----------



## foxidrive (Oct 20, 2012)

As Squashman mentioned, delayed expansion is one method - but it makes using ! in any filenames a problem, and music filenames often have a ! character in them.

So instead of using delayed expansion try this, where the parentheses are removed by using goto commands to skip sections. The variables should work with this technique - but % characters in filenames will still be an issue. I always rename such files and instead of % I type the word percent. ^ characters can be an issue too.


```
@echo off

:: Test.cmd
:: gettin another butt kickin
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
GOTO:EOF

:next
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^.[0-9]-[0-9][0-9] .*" >nul
if ERRORLEVEL 1 goto :next1


echo I found a number in %fname%
echo this is fname: "%fname%"
echo set "name=%~nx1%"
echo this  is name: "%name%"
echo set "name=%fname:~5%"
echo ren "%fname%" "%name%"
echo why the previous filename??!!         %name%

:next1

echo."%fname%"|findstr /r /c:"^.[0-9][0-9] .*" >nul
if ERRORLEVEL 1 goto :next2

echo I found a number in %fname%
echo this is fname: "%fname%"
echo set "name=%~nx1%"
echo this  is name: "%name%"
echo set "name=%fname:~3%"
echo ren "%fname%" "%name%"
echo why the previous filename??!!         %name%
:next2
```


----------



## ttx336 (Nov 7, 2012)

foxidrive said:


> As Squashman mentioned, delayed expansion is one method - but it makes using ! in any filenames a problem, and music filenames often have a ! character in them.
> 
> So instead of using delayed expansion try this, where the parentheses are removed by using goto commands to skip sections. The variables should work with this technique - but % characters in filenames will still be an issue. I always rename such files and instead of % I type the word percent. ^ characters can be an issue too.




```
:: strippit.cmd
@echo off
pushd "G:\"
for /f "delims=" %%z in ('dir /b /ad') do (
pushd "%%z"
call :start
popd
)
popd
GOTO:EOF



:start
:: from > Sett.cmd
cls
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
GOTO:EOF

:next
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^.[0-9]-[0-9][0-9] .*" >nul
if ERRORLEVEL 1 goto :next1
set "name=%fname:~5%"
ren "%fname%" "%name%"
goto :END


:next1
echo."%fname%"|findstr /r /c:"^.[0-9][0-9] .*" >nul
if ERRORLEVEL 1 goto :next2
set "name=%fname:~3%"
ren "%fname%" "%name%"
goto :END

:next2
@echo Bailing out at "next2"

:END
```
well, above is the working code.

And to speak to Squashman's suggestion, I did try using delayed expansion, before and again after his reply but did not get it to work either time. However, I think I now know why because when I was working through implementing your solution, I discovered that it was failing to set the variable because I had an @echo in the front of the line. As soon as I removed that it began to work. I suspect that would also have been the case with using delayed expansion.

Thank you both so very much, I ran it against the 32GB microSD... 3,609 songs cleaned up in less than 30 seconds, how do you NOT love that?

-Gary


----------



## Squashman (Apr 4, 2003)

If you tried delayed expansion in your previous code and it did not work then your code was still not correct.


```
@echo off
setlocal enabledelayedexpansion

:: Test.cmd
:: gettin another butt kickin
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
endlocal
GOTO:EOF

:next
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^.[0-9]-[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0 (
	echo I found a number in %fname%
	echo this is fname: "%fname%"
	set "name=%~nx1"
	echo this  is name: "!name!"
	set "name=%fname:~5%"
	echo ren "%fname%" "!name!"
	echo why the previous filename?         !name!
)
```


----------



## foxidrive (Oct 20, 2012)

ttx336 said:


> Thank you both so very much, I ran it against the 32GB microSD... 3,609 songs cleaned up in less than 30 seconds, how do you NOT love that?
> 
> -Gary


Bewdy!


----------



## ttx336 (Nov 7, 2012)

Squashman said:


> If you tried delayed expansion in your previous code and it did not work then your code was still not correct.
> 
> 
> ```
> ...


Yes, exactly, that is what I meant when I wrote:



> And to speak to Squashman's suggestion, I did try using delayed expansion, before and again after his reply but did not get it to work either time. However, I think I now know why because when I was working through implementing your solution, I discovered that it was failing to set the variable because I had an @echo in the front of the line. As soon as I removed that it began to work. I suspect that would also have been the case with using delayed expansion.


Here is a modified version of your code, this is essentially what I had:


```
@echo off
setlocal enabledelayedexpansion

:: Test.cmd
:: gettin another butt kickin
for /f "delims=" %%a in ('dir *.mp3 *.m4a /b /s /a-d') do call :next "%%a"
)
endlocal
GOTO:EOF

:next
set "fname=%~nx1"
echo."%fname%"|findstr /r /c:"^.[0-9]-[0-9][0-9] .*" >nul
if %ERRORLEVEL% EQU 0 (
	echo I found a number in %fname%
	echo this is fname: "%fname%"
	set "name=%~nx1"
	echo this  is name: "!name!"
	echo set "name=%fname:~5%"
	echo ren "%fname%" "!name!"
	echo why the previous filename?         !name!
)
```
And here is the output that it produces:


```
D:\Batch>stripexp
I found a number in 1-01 Green River.mp3
this is fname: "1-01 Green River.mp3"
this  is name: "1-01 Green River.mp3"
set "name=Green River.mp3"
ren "1-01 Green River.mp3" "1-01 Green River.mp3"
why the previous filename?         1-01 Green River.mp3

D:\Batch>
```
Compare that to:


```
D:\Batch>stripexp
I found a number in 1-01 Green River.mp3
this is fname: "1-01 Green River.mp3"
this  is name: "1-01 Green River.mp3"
ren "1-01 Green River.mp3" "Green River.mp3"
why the previous filename?         Green River.mp3
```
The *only* difference is I had "echo" in front of "set" -> echo set "name=%fname:~5%" - and that is enough to break it...


----------

