0

If in windows there is a folder with several files, say c:/folder with files and inside it has random name files.

And I have a .txt file with several words, say c:/words/wordstofind.txt

I would like to know if there is a way that pc can enter check if any of the words in wordstofind.txt exist inside each of the files in c:/folder with files, and if at least 1 exist, then give me the filenames of those files within that folder that do contain any of the words in wordstofind.txt

I dont need to know which word it found, and also if it finds any word, it can add the filename of that file to result directly and pass to searching the next file within the folder (1 result is enought to go to the result file).

Result file to be saved into C:/results/resultfilenames.txt

When I open the resultfilenames.txt, it should contain only the name of the files that contain any of those words specified, not the folder if possible (whch would be the same for all).

Thanks

9
  • Yes, this is possible. It's clear you want a command line solution but do you have a preference regarding implementation (e.g. Batch, PowerShell, any scripting language)? Jan 22, 2018 at 5:35
  • Hello, thanks for the answer. Yes, I would like to do it in windows CMD. I just found this command below makes the job however its result is showing the folder/filename.txt in the result file (only need the filename.txt).Also, when I added /I to it (before the /S) it is not disconsidering the case of the letters (example: if I put in wordstosearch.txt file the word "hello", i need it to find either "Hello" or "hello" or "HeLlo" or etc ways upper or lower case not mattering). Would you know how to fix this? Thanks Formula: FINDSTR /S /g:wordstosearch.txt /f:listoffilestosearch.txt > result.txt
    – Joao
    Jan 22, 2018 at 6:15
  • Hello, about the case seems is working like this now. However, I am doing the same test many times, and sometimes it gives the correct result and sometimes it doesnt give the result that should be there. How accurate is this findstr? Is there another way to do this very accurately in windows? if so, could you explain how, this is, do i need to download any plugin and how to use it for this purpose? thanks
    – Joao
    Jan 22, 2018 at 9:35
  • When the file contains lots of texts big sizes with blanks, spaces, empty lines, symbols etc, is where it is failing to search the words. Should I add another command so it can read this well? Thanks
    – Joao
    Jan 22, 2018 at 9:40
  • 1
    findstr has a bunch of issues. At a guess, your varying results may be due to trying to find multiple literal search strings. Jan 22, 2018 at 9:57

1 Answer 1

0

For a native Windows solution, FINDSTR is a possible option. For your use case, you could try:

findstr /l /s /i /m /g:searchwords.txt /f:filestosearch.txt > results.txt 

This tells FINDSTR to (respectively):

  • Use the search words as string literals (rather than regular expressions).

  • Recurse sub-folders.

  • Ignore case sensitivity.

  • Print only file names (which happens to include the full directory path).

Note, however, FINDSTR has undocumented limits and bugs which may not make it a suitable option.

For a non-native solution, you might be interested in a port of the grep utility, such as GNUWin32 grep. While grep implementations can vary in the options they support, GNUWin32 grep is a port of GNU grep (albeit currently v2.5.4 rather than v3.0) which can read search terms from a file. For your use case, you can try:

grep -rilf C:\path\to\searchwords.txt C:\path\to\search > results.txt

This tells grep to (respectively):

  • Recurse sub-folders.

  • Ignore case sensitivity.

  • Suppress normal output (list files only, including full path).

  • Pull search terms from a text file.

Both FINDSTR and grep return full paths to a file, so you will likely need to do additional processing on the output of either. Be aware, however, that unlike FINDSTR, grep options are typically case-sensitive. For instance, -L is not the same option as -l (lowercase L). Any paths with spaces require double quotes ("") as normal.

If you wish to search only specific files, you can list them on the command line individually (e.g. doc1.txt doc2.txt doc3.txt) in place of the directory. You can use full paths (e.g.C:\path\to\doc1.txt) as necessary.

It's also worth mentioning that the reason I have placed the "searchwords.txt" file in a separate directory is that GNUWin32 grep will include this file in the "matched" items otherwise.

Finally, while it shouldn't be a deal-breaker in most instances, GNUWin32 grep uses Unix-style line feeds for its output, as well as a mix of \ and / for paths.

Note that there is some additional explanation of these last two GNUWin32 grep specific quirks at end of this answer... so you may wish to read that as well. =)

Fixing Output With sed

Since you want just the file names, we can actually use another GNUWin32 utility called sed to obtain these. This is a port of GNU sed, a "non-interactive command-line text editor". What this means is that this program can take text input from the command line, modify it in a standardized way, and output that modified data.

In our case with GNUWin32 grep, we can use it to eliminate everything before each file name with:

sed s/.\+[/+]//

Furthermore, we can pipe | the output from grep to sed like so:

grep -rilf C:\path\to\searchwords.txt C:\path\to\search | sed s/.\+[/+]// > results.txt

This will leave just the file name in "results.txt" and has the added benefit of eliminating any issues with / and Unix-style line feeds (all / are removed and, at least when piping like this, sed outputs normal Windows line breaks).

The breakdown of the sed command is as follows:

  • s/ is the beginning of the substitute command.
  • .\+[/+] is a regular expression (what we want to find -- in this case everything up to and including the last / in our grep output).
  • // is, respectively, the required / separator between our item to find and our replacement, no space (a blank replacement) and the final / required for all sed substitute commands.
  • sed can also us other separators e.g. + in case of conflicts (say, with directory slashes).
  • A missing final / will result in an "unterminated 's' command" error.

As a small caveat, the sed command above eliminates sub-directory information as well, so the file names returned may not all be in the same (root) directory.

You can read more about GNU sed regular expressions here.


GNUWin32 grep Quirks

Newlines

Newlines are normally hidden control characters in a text document which signal to an application where to separate lines of text. Importantly, these can vary from operating system to operating system.

In the case of Unix-style systems (where grep originated), this is a simple Line Feed, represented as /n e.g.

line 1 /n
line 2 /n

Windows is similar but uses an additional Carriage Return, represented as /r, before its Line Feed. This results in a combined /r/n rather than just /n.

While not usually an issue, some Windows programs (such as Windows Notepad) behave differently with single Line Feeds (/n). One common issue is making lines run together e.g.

line1line2

Since GNUWin32 grep produces /n control characters only and not /r/n, this can cause output sent to a file (via ">" above) to have readability or other issues in some instances. If necessary, this can be fixed by either replacing the /n control characters with /r/n (possible through additional scripting) or by simply using a program that supports reading/replacing these characters (such as Notepad++).

Reversed Separators

Another inherited quirk is the difference in the separators used for directories (paths) between Unix-style and Windows systems. On Unix-style systems, the separators are forward slashes e.g.

/path/to/some/file.txt

Windows, however, uses backwards slashes e.g.

C:\path\to\some\directory

GNUWin32 grep oddly combines the two, using the normal backwards slashes for the primary directory path and forward slashes for listing file matching results e.g.

C:\path\to\some\directory/match1.txt
C:\path\to\some\directory/subdirectory/match2.txt

This quirk can be overcome with (again) additional scripting or a simple Find/Replace in any normal text editor.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .