Search code examples
windowsbatch-fileerror-handlingcommand-promptfindstr

FINDSTR: help understanding results. Returns nothing, but no error when there is one expected?


I am writing a batch file. part of the program will compare the list of files in a 'source' folder. With the contents of a list in a text file.

I loop through each file in the folder, and search for its filename in the text file using FINDSTR

Everything works until there is a filename in the source folder that doesnt exist in the text file.

the findstr code:

for /f %%o in ('findstr %name% old.txt') do (
    echo o=%%o >> result.txt
    if %%o==%name% (
        echo %name% exists
    ) ELSE (
        echo %name% does not exists
    )
)

Again, the problem occurs when FINDSTR searches for a filename that is not in the text file.

when it reaches that point it outputs the variable %%o as being '%o' and echos nothing. So it sends nothing to the results.txt.

This doesnt trigger an ERRORLEVEL change but also will not echo anything. I have tried outputing the errorlevels but they are also empty. I just dont understand what FINDSTR is doing in this instance.

the FULL batch file: (its my first one. forgive any mistakes)

  ::return the raw (/b) list of files 
  FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo @path" > new.txt

  ::pull file path for each file and send to subroutine
  for /f %%n in ('FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo @path"') do (

    call :dequote %%n

  )

::subroutine for removing quotes 
::and returning the filename, extension, and path
:dequote
set fullPath=%~f1
set fileName=%~n1
set fileExt=%~x1
set filePath=%~dp1
set name=%fileName%& set npath=%filePath%& set ext=%fileExt%& set fpath=%fullPath%
echo %fpath%
echo %npath%
echo %name%
echo %ext%

for /f %%o in ('findstr %name% old.txt') do (
    echo o=%%o >> result.txt
    if %%o==%name% (
        echo %name% exists
    ) ELSE (
    echo %name% does not exists
    )
)

This only happens on the last filename sent to findstr. Any suggestions or direction would be very appreciated. Ive tried and read everything I can get my hands on.

Thank You for your time.


UPDATE: 9-9-15

Here is the working final batch file i created using the help on this page. It creates a hotfolder that will edit any new files added to it until you stop the script from running:

  :start

  :: return the raw (/b) list of files and full path to source text
  FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo @path" > source.txt
  IF %ERRORLEVEL% EQU 1 goto :start

  ::join new and old data, return only what is shared in common (/g)
  findstr /I /L /G:"source.txt" "output.txt" > found.txt
  IF %ERRORLEVEL% EQU 1 copy /y source.txt notFound.txt

  ::join found file names and source filenames, return those that do not have a match
  findstr /I /L /V /G:"found.txt" "source.txt" >> notFound.txt
  IF %ERRORLEVEL% EQU 2 echo error no match

  ::for each line of notFound.txt, dequote and break apart
  for /f %%n in (notFound.txt) do (
    echo n=%%n
    call :dequote %%n
  )

  :dequote
  set fullPath=%~f1
  set fileName=%~n1
  set fileExt=%~x1
  set filePath=%~dp1
  set name=%fileName%& set npath=%filePath%& set ext=%fileExt%& set fpath=%fullPath%
  echo %fpath%
  echo %npath%
  echo %name%
  echo %ext%

  cd %nPath%
  if NOT [%1]==[] (
    echo converted %name%
    convert -negate -density 600 -colorspace gray flatField.cr2 %name%%ext% -compose Divide -composite %name%.tif
    move %name%.tif %~dp0output
    cd %~dp0
    del notFound.txt
    copy /y source.txt output.txt
    ) ELSE (
     echo end of batch else
     cd %~dp0
  )

Solution

  • Loop variables must be referenced with %% in a batch file because percent sign has a special meaning and must be therefore escaped with another percent sign in a batch file to specify it literally. This is the reason why on running the batch file with echo on in a command prompt window results in getting %%o in the batch file displayed as %o on execution.

    Command FOR as used in

    for /f %%o in ('findstr %name% old.txt') do
    

    processes the output written to stdout by the called command findstr. But findstr does not write anything to standard output when it searched for one or more strings in a file and could not find any matching string in any line of the file.

    So command for can't process anything and therefore none of the commands after do are processed at all in this case.

    Assuming the list file contains only file names without path, the following commented batch file can be used to get with 1 execution of command dir and just 1 or 2 executions of console application findstr the two lists containing the file names in folder being found and being not found in the list file. The batch file is written for not producing empty files.

    @echo off
    setlocal
    set "ListFile=C:\Temp\List.txt"
    if not exist "%ListFile%" goto NoListFile
    
    set "SourceFolder=C:\Temp\Test"
    if not exist "%SourceFolder%\*" goto NoSourceFolder
    
    set "AllFileNames=%TEMP%\AllFileNames.txt"
    set "FoundFileNames=%TEMP%\FoundFileNames.txt"
    set "NotFoundFileNames=%TEMP%\NotFoundFileNames.txt"
    
    rem Get alphabetic list of files in source folder without path.
    dir /A /B /ON "%SourceFolder%" >"%AllFileNames%"
    
    rem Find all file names in list file with a case-insensitive
    rem search matching completely a file name in list file and
    rem output the found file names to another list file.
    %SystemRoot%\system32\findstr.exe /I /L /X "/G:%AllFileNames%" "%ListFile%" >"%FoundFileNames%"
    if errorlevel 1 goto NoFileNameFound
    
    rem Find all file names with a case-insensitive search found
    rem before in all file names list and output the lines not
    rem containing one of the file names to one more list file.
    %SystemRoot%\system32\findstr.exe /I /L /V "/G:%FoundFileNames%" "%AllFileNames%" >"%NotFoundFileNames%"
    if errorlevel 1 goto AllFileNamesFound
    
    rem Some file names are found in list file and others not.
    del "%AllFileNames%"
    goto :EndBatch
    
    :NoFileNameFound
    move /Y "%AllFileNames%" "%NotFoundFileNames%"
    del "%FoundFileNames%"
    goto EndBatch
    
    :AllFileNamesFound
    del "%AllFileNames%"
    del "%NotFoundFileNames%"
    goto EndBatch
    
    :NoListFile
    echo %~f0:
    echo Error: No list file %ListFile%
    goto EndBatch
    
    :NoSourceFolder
    echo %~f0:
    echo Error: No folder %SourceFolder%
    
    :EndBatch
    endlocal
    

    For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

    • del /?
    • dir /?
    • findstr /?
    • goto /?
    • if /?
    • move /?
    • set /?