joacampb
joacampb

Reputation: 177

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
  )

Upvotes: 0

Views: 2685

Answers (2)

Mofi
Mofi

Reputation: 49127

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 /?

Upvotes: 1

foxidrive
foxidrive

Reputation: 41242

This is a method to give you a list of filenames which don't exist in the file.txt

@echo off
cd /d "c:\folder\to\check"
for %%a in (*) do findstr /i "%%~nxa" "file.txt" >nul || echo "%%a" is missing
pause

It uses %%~nxa instead of %%a in case subdirectories are used at some point.

Upvotes: 0

Related Questions