问题
I'm new to Windows batch programming and to Stack Overflow, so please forgive me if I ask anything that's blatantly obvious to you seasoned, talented folks. I'm using Windows batch (.bat) to find files containing a certain string using findstr
. However, I'm trying to skip certain folders within a directory.
setlocal EnableDelayedExpansion
set basedir=C:\folder
for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
findstr /i /m /s /c:"request" %basedir%\%%g *.* > %basedir%\Projects\list.txt
)
When I look in list.txt, the file output from findstr
, I find that the folders I told it not to search were searched. That is, the output looks like this:
C:\folder\somefile.rtf
C:\folder\Requests\anotherfile.rtf
C:\folder\Projects\dontsearchme.txt
C:\folder\Archive\dontsearchmeeither.txt
C:\folder\Archive\Projects\dontsearchme.txt
If it had worked correctly, only C:\folder\somefile.rtf
and C:\folder\Requests\anotherfile.rtf
would have been included in list.txt. To test the looping code, I used the following:
setlocal EnableDelayedExpansion
set basedir=C:\folder
for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
echo %basedir%\%%g
)
That code works as desired; it skips the Projects and Archive folders. I assume that the problem has something to do with how I'm calling findstr
but I haven't been able to identify the error of my ways. Any insight would be much appreciated!
Thanks so much!
-Alex
回答1:
The FINDSTR /S option is causing it to search all folders, thus bypassing the intent of your FOR loop.
Stephan did successfully diagnose another problem with your code regarding redirection using overwrite instead of append mode.
But there is a much simpler method to get your desired result. Simply let FINDSTR search all folders, and pipe the result to an additional FINDSTR to remove results containing the unwanted folders. Since there is no loop, you can safely use owverwrite mode for redirection.
findstr /misl request "%basedir%\*" | findstr /liv "\\projects\\ \\archive\\" >"%basedir%\Projects\list.txt"
EDIT
The above simple solution will waste time searching folders that will later get excluded. This could waste valuable time if those folders are huge.
The following script will not bother scanning the "%basedir%\Projects" or "%basedir%\Archive" folders.
@echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder
>"%basedir%\Projects\list.txt" (
findstr /mil request "%basedir%\*"
for /f "eol=: delims=" %%F in (
'dir /a:d-h /b %basedir% ^| findstr /vixl "projects archive"'
) do findstr /smil request "%basedir%\%%F\*"
)
If you want to skip all folders named "Projects" or "Archive", regardless where they appear in the tree, then:
@echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder
>"%basedir%\Projects\list.txt" (
findstr /mil request "%basedir%\*"
for /f "eol=: delims=" %%F in (
'dir /s /a:d-h /b %basedir% ^| findstr /vir "[\\]projects[\\] [\\]archive[\\] [\\]projects$ [\\]archive$"'
) do findstr /mil request "%%F\*"
)
回答2:
I had a similar problem: I needed to use findstr to search all .js files except those in the node_modules folder (i.e., I wanted to search my code, but not the code of any imported modules). This is the command I used:
dir /S /B *.js | findstr /v /i node_modules | findstr /i /F:/ todo
Breaking that down:
dir /S /B *.js
will output the full path of all .js files in the current directory and all subdirectoriesfindstr /v /i node_modules
filters that list of paths and removes any path that contains the string "node_modules". (The /v flag makes findstr output lines that do not match.)findstr /i /F:/ todo
- The "/F:/" tells findstr to accept a list of file paths to search from the console.
So, only files that make it through the "node_modules" filter get searched.
回答3:
your problem is: with the redirection >
you overwrite your list.txt every time; the last time you overwrite it with an empty string.
Use >>
(append to file) instead. The rest of your code is working for me.
回答4:
Your code have a couple points difficult to follow. You want to skip folders, but for /f %%g in ('dir /a:-h /b %basedir%
command get all non-hidden names, including both files and folders. At end you use >
to store the results, so just the output of last findstr ... %%g
is stored in that file. You must use >>
instead as Stephan indicate. However, I still don't understand how you get that result!
I suggest you to modify your code in order to made it simpler, so it may be easier to follow and detect possible errors. For example:
setlocal EnableDelayedExpansion
set basedir=C:\folder
set omitfolders=\Projects\Archive\
cd %basedir%
for /D %%g in (*) do (
if "!omitfolders:\%%g\=!" equ "%omitfolders%" (
findstr /i /m /s /c:"request" %basedir%\%%g\*.* >> %basedir%\Projects\list.txt
)
)
The if "!omitfolders:\%%g\=!" equ "%omitfolders%"
command test if the folder name is not in omitfolders
variable.
来源:https://stackoverflow.com/questions/20076262/findstr-and-skipping-folders