CMD - 如何列出包含某些单词的文本文件

CMD - 如何列出包含某些单词的文本文件

如果在 Windows 中有一个包含多个文件的文件夹,比如说 c:/folder with files,并且里面有随机名称的文件。

我有一个包含几个单词的 .txt 文件,比如 c:/words/wordstofind.txt

我想知道是否有一种方法可以让电脑输入检查 wordstofind.txt 中的任何单词是否存在于 c:/folder 中的每个文件中,如果至少存在 1 个,则给我该文件夹中包含 wordstofind.txt 中的任何单词的文件的文件名

我不需要知道它找到了哪个单词,而且如果它找到了任何单词,它可以直接将该文件的文件名添加到结果中并转到搜索文件夹内的下一个文件(1 个结果足以转到结果文件)。

结果文件保存到 C:/results/resultfilenames.txt

当我打开 resultfilenames.txt 时,它应该仅包含包含指定的任何单词的文件的名称,而不是文件夹(如果可能的话)(对于所有文件来说都是相同的)。

谢谢

答案1

对于本机 Windows 解决方案,查找字符串是一个可行的选择。对于您的用例,您可以尝试:

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

这将分别告诉 FINDSTR:

  • 使用搜索词作为字符串文字(而不是正则表达式)。

  • 递归子文件夹。

  • 忽略大小写。

  • 仅打印文件名(恰好包含完整的目录路径)。

但请注意,FINDSTR 有未记录的限制和错误这可能不是一个合适的选择。

对于非本地解决方案,您可能对以下移植感兴趣grep实用程序,例如GNUWin32 grep。虽然 grep 实现在支持的选项方面可能有所不同,但 GNUWin32 grep 是GNU grep(虽然目前是 v2.5.4 而不是 v3.0)它可以从文件中读取搜索词。对于您的用例,您可以尝试:

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

这分别告诉 grep:

  • 递归子文件夹。

  • 忽略大小写。

  • 抑制正常输出(仅列出文件,包括完整路径)。

  • 从文本文件中提取搜索词。

FINDSTR 和 grep 都返回文件的完整路径,因此您可能需要对两者的输出进行额外处理。但请注意,与 FINDSTR 不同,grep 选项通常区分大小写。例如,-L 是不是与 -l(小写 L)相同的选项。任何带有空格的路径都需要双引号(“”)。

如果您只想搜索特定文件,您可以在命令行中单独列出它们(例如doc1.txt doc2.txt doc3.txt),而不是目录。您可以C:\path\to\doc1.txt根据需要使用完整路径(例如)。

还值得一提的是,我将“searchwords.txt”文件放在单独目录中的原因是,否则 GNUWin32 grep 会将此文件包含在“匹配”项目中。

最后,虽然在大多数情况下这不应该成为一个交易破坏者,但 GNUWin32 grep 使用 Unix 风格的换行符作为其输出,以及和的混合\作为/路径。

请注意,在此答案的末尾对最后两个 GNUWin32 grep 特定怪癖有一些额外的解释...所以您可能也希望阅读它。=)

使用 sed 修复输出

由于您只需要文件名,我们实际上可以使用另一个名为sed获得这些。这是GNU sed,一个“非交互式命令行文本编辑器”。这意味着该程序可以从命令行获取文本输入,以标准化方式对其进行修改,并输出修改后的数据。

在我们的 GNUWin32 grep 示例中,我们可以使用它来消除每个文件名之前的所有内容:

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

此外,我们可以将|grep 的输出通过管道传输到 sed,如下所示:

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

这将只在“results.txt”中保留文件名,并且还有消除任何与/Unix 样式换行符有关的问题的额外好处(所有内容/都会被删除,至少在像这样进行管道传输时,sed 会输出正常的 Windows 换行符)。

sed命令的具体内容如下:

  • s/是替代命令的开始。
  • .\+[/+]是一个正则表达式(我们想要找到的——在本例中是/grep 输出中的所有内容,包括最后一个内容)。
  • //分别是/我们要查找的项目和替换项之间所需的分隔符、无空格(空白替换)以及/所有 sed 替换命令所需的最后一个分隔符。
  • sed 还可以使用其他分隔符,例如,在发生冲突的情况下使用 +(例如,与目录斜杠)。
  • 缺少最后一个字符/将导致“未终止的‘s’命令”错误。

需要注意的是,上面的 sed 命令也消除了子目录信息,因此返回的文件名可能并不都在同一个(根)目录中。

您可以阅读有关 GNU sed 正则表达式的更多信息这里


GNUWin32 grep 怪癖

换行符

换行符通常是文本文档中隐藏的控制字符,用于向应用程序发出信号,指示在何处分隔文本行。重要的是,这些可能因操作系统而异。

如果是Unix 风格系统(grep 的起源),这是一个简单的换行符,表示为/n例如

line 1 /n
line 2 /n

/rWindows 与之类似,但在换行符前使用了一个额外的回车符,表示为。这样就得到了一个组合的/r/n,而不仅仅是/n

虽然通常不是问题,但某些 Windows 程序(如 Windows 记事本)对单个换行符 ( /n) 的行为有所不同。一个常见问题是使行连在一起,例如

line1line2

由于 GNUWin32 grep/n仅生成控制字符而不生成/r/n,这可能会导致发送到文件的输出(通过上面的 ">")在某些情况下具有可读性或其他问题。如有必要,可以通过将/n控制字符替换为/r/n(可以通过其他脚本)或简单地使用支持读取/替换这些字符的程序(例如记事本++)。

反向分隔符

另一个继承的怪癖是 Unix 风格系统和 Windows 系统之间用于目录(路径)的分隔符不同。在 Unix 风格的系统上,分隔符是正斜杠,例如

/path/to/some/file.txt

但是,Windows 使用反斜杠,例如

C:\path\to\some\directory

GNUWin32 grep 奇怪地将两者结合在一起,使用正常的反斜杠表示主目录路径,使用正斜杠列出文件匹配结果,例如

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

可以通过(再次)附加脚本或任何普通文本编辑器中的简单查找/替换来克服这个问题。

相关内容