1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Solved: cannot get proper syntax for FINDSTR

Discussion in 'DOS/Other' started by ttx336, Feb 23, 2013.

Thread Status:
Not open for further replies.
Advertisement
  1. ttx336

    ttx336 Thread Starter

    Joined:
    Nov 7, 2012
    Messages:
    49
    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...

    Code:
    @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...

    Code:
    D:\Dropbox\Computers\Batch>strippit
    
    D:\Dropbox\Computers\Batch>@echo off
    '@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
     
  2. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    Try this. The quotes are necessary for poison characters and so the leading . in the findstr term eats the first quote.

    Code:
    @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
     
  3. ttx336

    ttx336 Thread Starter

    Joined:
    Nov 7, 2012
    Messages:
    49
    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:

    Code:
    :: 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:

    Code:
    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):

    Code:
    :: 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

    Code:
    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
     
  4. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    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.
     
  5. ttx336

    ttx336 Thread Starter

    Joined:
    Nov 7, 2012
    Messages:
    49
    ...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:

    Code:
    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):

    Code:
    :: 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
     
  6. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    You are manipulating a variable inside a code block. Remember from a previous thread we had talked about the use of delayed expansion.
     
  7. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    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.

    Code:
    @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
    
     
  8. ttx336

    ttx336 Thread Starter

    Joined:
    Nov 7, 2012
    Messages:
    49
    Code:
    :: 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
     
  9. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    If you tried delayed expansion in your previous code and it did not work then your code was still not correct.

    Code:
    @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!
    )
     
  10. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    Bewdy! :)
     
  11. ttx336

    ttx336 Thread Starter

    Joined:
    Nov 7, 2012
    Messages:
    49
    Yes, exactly, that is what I meant when I wrote:

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

    Code:
    @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:

    Code:
    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:

    Code:
    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...
     
  12. Sponsor

As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 733,556 other people just like you!

Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/1090664

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice