如何使用 findstr 从文件中删除与列表文件中找到的字符串匹配的行?
How to use findstr to remove lines from a file that match strings found in a list file?
我正在尝试使用 findstr 删除与在另一个文件中找到的搜索字符串相匹配的行。这是我一直在尝试使用但它似乎不起作用。
dir %ProjectDir%TypeScript\*.ts /b /s > Files.txt
findstr /v /i /g:%ProjectDir%TypeScript\strictFiles.txt Files.txt > tsFiles.txt
编辑 这似乎也不起作用:
dir %ProjectDir%TypeScript\*.ts /b /s | findstr /v /i /g:%ProjectDir%TypeScript\strictFiles.txt > tsFiles.txt
简短而不完整的答案是您没有指定 findstr
的 /L
开关,它强制执行文字搜索。没有它,第一个搜索字符串决定是选择文字搜索还是正则表达式模式。由于搜索字符串中包含文件名,其中包含将基本名称与名称扩展名分开的句点,这也是正则表达式模式中的元字符,因此findstr
最有可能选择该模式。
此外,您还应该提供 /X
开关以不过滤掉错误的项目。例如,当缺少 /X
选项时,像 D:\Data\some
这样的路径也会匹配 D:\Data\some\file.ext
。
长而全面的答案考虑到 findstr
并没有让生活变得那么轻松。
让我们假设命令行...:[=62=]
dir /S /B /A:-D "D:\Project\TypeScript\*.ts" > "Files.txt"
...生成 Files.txt
中的文件路径列表,如下所示,...:[=62=]
D:\Project\TypeScript\sample.ts
D:\Project\TypeScript\restricted.ts
D:\Project\TypeScript\excluded.ts
D:\Project\TypeScript\not-excluded.ts
D:\Project\TypeScript\ancillary.ts
D:\Project\TypeScript\[special].ts
D:\Project\TypeScript\data\test.ts
D:\Project\TypeScript\data\confidential.ts
D:\Project\TypeScript\data\arbitrary.ts
D:\Project\TypeScript\data\.config.ts
D:\Project\TypeScript\data\other.config.ts
D:\Project\TypeScript\data.config.ts
D:\Project\TypeScript\conf.ts\wrong.ts
...文件 strictFiles.txt
包含此...:
D:\Project\TypeScript\restricted.ts
D:\Project\TypeScript\excluded.ts
D:\Project\TypeScript\[special].ts
D:\Project\TypeScript\confidential.ts
D:\Project\TypeScript\data\.config.ts
D:\Project\TypeScript\conf.ts
...从 Files.txt
.
中过滤掉
您会期望命令行...:[=62=]
findstr /L /X /I /V /G:"strictFiles.txt" "Files.txt" > "tsFiles.txt"
...到 return 输出文件 tsFiles.txt
,...:[=62=]
D:\Project\TypeScript\sample.ts
D:\Project\TypeScript\not-excluded.ts
D:\Project\TypeScript\ancillary.ts
D:\Project\TypeScript\data\test.ts
D:\Project\TypeScript\data\confidential.ts
D:\Project\TypeScript\data\arbitrary.ts
D:\Project\TypeScript\data\other.config.ts
D:\Project\TypeScript\data.config.ts
D:\Project\TypeScript\conf.ts\wrong.ts
...但实际上写的是:
D:\Project\TypeScript\sample.ts
D:\Project\TypeScript\not-excluded.ts
D:\Project\TypeScript\ancillary.ts
D:\Project\TypeScript\[special].ts
D:\Project\TypeScript\data\test.ts
D:\Project\TypeScript\data\confidential.ts
D:\Project\TypeScript\data\arbitrary.ts
D:\Project\TypeScript\data\.config.ts
D:\Project\TypeScript\data\other.config.ts
D:\Project\TypeScript\conf.ts\wrong.ts
原因是 findstr
,尽管由于 /L
选项而处于文字搜索模式,但仍会检测正则表达式模式的元字符,并允许通过在前面加上\
。 strictFiles.txt
上面的示例内容中的句点.
和左括号[
就是这样的元字符,并且都在前面加了路径分隔符\
,所以它们是被视为转义,因此被解释为 .
和 [
,或者换句话说,前面的 \
被忽略。
要解决这个问题,您需要在 strictFiles.txt
中转义每个 \
,在前面加上另一个 \
,以避免元字符看起来转义为 [=20] =] -- 请参阅此脚本以了解可能的方法:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\Project\TypeScript" & rem // (path of root directory)
set "_MASK=*.ts" & rem // (file search pattern)
set "_LIST=.\Files.txt" & rem // (path to file list)
set "_EXCL=.\strictFiles.txt" & rem // (path to exclusion list)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary exclusion list)
set "_FILT=.\tsFiles.txt" & rem // (path to filtered file list)
if not defined _FILT set "_FILT=con"
rem // Generate list of files:
dir /S /B /A:-D "%_ROOT%\%_MASK%" > "%_LIST%"
rem // Modify exclusion list:
rem /* replace every path separator `\` by an escaped one `\`,
rem so no other characters can appear escaped to `findstr`: */
> "%_TEMP%" (
for /F "usebackq delims= eol=|" %%F in ("%_EXCL%") do (
set "FILE=%%F"
setlocal EnableDelayedExpansion
echo(!FILE:\=\!
endlocal
)
)
rem // Filter out files that occur in modified exclusion list:
findstr /L /X /V /I /G:"%_TEMP%" "%_LIST%" > "%_FILT%"
rem // Clean up temporary files:
del "%_LIST%" "%_TEMP%"
endlocal
exit /B
如果您的排除列表,比如这次 strictFileNames.txt
,包含纯文件名而不是完整的文件路径,例如,...:[=62=]
restricted.ts
excluded.ts
[special].ts
confidential.ts
.config.ts
conf.ts
...方法略有不同,因为只考虑文件列表的最后一个路径元素 Files.txt
。为此,您需要在排除列表的每个文件名之前加上一个路径分隔符,同样是一个像 \
这样的转义分隔符,以避免错误匹配;例如,file.ext
将匹配 D:\Data\file.ext
和 D:\Data\X-file.ext
,但 \file.ext
将仅匹配前者,因为 /X
选项已替换为 [=53] =]这次。
这是一个完成该任务的脚本:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\Project\TypeScript" & rem // (path of root directory)
set "_MASK=*.ts" & rem // (file search pattern)
set "_LIST=.\Files.txt" & rem // (path to file list)
set "_EXCL=.\strictFileNames.txt" & rem // (path to exclusion list)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary exclusion list)
set "_FILT=.\tsFiles.txt" & rem // (path to filtered file list)
if not defined _FILT set "_FILT=con"
rem // Generate list of files:
dir /S /B /A:-D "%_ROOT%\%_MASK%" > "%_LIST%"
rem // Modify exclusion list:
rem /* precede every file with an escaped path separator `\`,
rem so no other characters can appear escaped to `findstr`: */
> "%_TEMP%" (
for /F "usebackq delims= eol=|" %%F in ("%_EXCL%") do (
echo(\%%F
)
)
rem // Filter out files that occur in modified exclusion list:
findstr /L /E /V /I /G:"%_TEMP%" "%_LIST%" > "%_FILT%"
rem // Clean up temporary files:
del "%_LIST%" "%_TEMP%"
endlocal
exit /B
选择了以上所有示例文件内容,以便您可以轻松地使用它们并查看使用选项 /X
或 /E
以及加倍路径分隔符时的差异 \
与否。
我正在尝试使用 findstr 删除与在另一个文件中找到的搜索字符串相匹配的行。这是我一直在尝试使用但它似乎不起作用。
dir %ProjectDir%TypeScript\*.ts /b /s > Files.txt
findstr /v /i /g:%ProjectDir%TypeScript\strictFiles.txt Files.txt > tsFiles.txt
编辑 这似乎也不起作用:
dir %ProjectDir%TypeScript\*.ts /b /s | findstr /v /i /g:%ProjectDir%TypeScript\strictFiles.txt > tsFiles.txt
简短而不完整的答案是您没有指定 findstr
的 /L
开关,它强制执行文字搜索。没有它,第一个搜索字符串决定是选择文字搜索还是正则表达式模式。由于搜索字符串中包含文件名,其中包含将基本名称与名称扩展名分开的句点,这也是正则表达式模式中的元字符,因此findstr
最有可能选择该模式。
此外,您还应该提供 /X
开关以不过滤掉错误的项目。例如,当缺少 /X
选项时,像 D:\Data\some
这样的路径也会匹配 D:\Data\some\file.ext
。
长而全面的答案考虑到 findstr
并没有让生活变得那么轻松。
让我们假设命令行...:[=62=]
dir /S /B /A:-D "D:\Project\TypeScript\*.ts" > "Files.txt"
...生成 Files.txt
中的文件路径列表,如下所示,...:[=62=]
D:\Project\TypeScript\sample.ts D:\Project\TypeScript\restricted.ts D:\Project\TypeScript\excluded.ts D:\Project\TypeScript\not-excluded.ts D:\Project\TypeScript\ancillary.ts D:\Project\TypeScript\[special].ts D:\Project\TypeScript\data\test.ts D:\Project\TypeScript\data\confidential.ts D:\Project\TypeScript\data\arbitrary.ts D:\Project\TypeScript\data\.config.ts D:\Project\TypeScript\data\other.config.ts D:\Project\TypeScript\data.config.ts D:\Project\TypeScript\conf.ts\wrong.ts
...文件 strictFiles.txt
包含此...:
D:\Project\TypeScript\restricted.ts D:\Project\TypeScript\excluded.ts D:\Project\TypeScript\[special].ts D:\Project\TypeScript\confidential.ts D:\Project\TypeScript\data\.config.ts D:\Project\TypeScript\conf.ts
...从 Files.txt
.
您会期望命令行...:[=62=]
findstr /L /X /I /V /G:"strictFiles.txt" "Files.txt" > "tsFiles.txt"
...到 return 输出文件 tsFiles.txt
,...:[=62=]
D:\Project\TypeScript\sample.ts D:\Project\TypeScript\not-excluded.ts D:\Project\TypeScript\ancillary.ts D:\Project\TypeScript\data\test.ts D:\Project\TypeScript\data\confidential.ts D:\Project\TypeScript\data\arbitrary.ts D:\Project\TypeScript\data\other.config.ts D:\Project\TypeScript\data.config.ts D:\Project\TypeScript\conf.ts\wrong.ts
...但实际上写的是:
D:\Project\TypeScript\sample.ts D:\Project\TypeScript\not-excluded.ts D:\Project\TypeScript\ancillary.ts D:\Project\TypeScript\[special].ts D:\Project\TypeScript\data\test.ts D:\Project\TypeScript\data\confidential.ts D:\Project\TypeScript\data\arbitrary.ts D:\Project\TypeScript\data\.config.ts D:\Project\TypeScript\data\other.config.ts D:\Project\TypeScript\conf.ts\wrong.ts
原因是 findstr
,尽管由于 /L
选项而处于文字搜索模式,但仍会检测正则表达式模式的元字符,并允许通过在前面加上\
。 strictFiles.txt
上面的示例内容中的句点.
和左括号[
就是这样的元字符,并且都在前面加了路径分隔符\
,所以它们是被视为转义,因此被解释为 .
和 [
,或者换句话说,前面的 \
被忽略。
要解决这个问题,您需要在 strictFiles.txt
中转义每个 \
,在前面加上另一个 \
,以避免元字符看起来转义为 [=20] =] -- 请参阅此脚本以了解可能的方法:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\Project\TypeScript" & rem // (path of root directory)
set "_MASK=*.ts" & rem // (file search pattern)
set "_LIST=.\Files.txt" & rem // (path to file list)
set "_EXCL=.\strictFiles.txt" & rem // (path to exclusion list)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary exclusion list)
set "_FILT=.\tsFiles.txt" & rem // (path to filtered file list)
if not defined _FILT set "_FILT=con"
rem // Generate list of files:
dir /S /B /A:-D "%_ROOT%\%_MASK%" > "%_LIST%"
rem // Modify exclusion list:
rem /* replace every path separator `\` by an escaped one `\`,
rem so no other characters can appear escaped to `findstr`: */
> "%_TEMP%" (
for /F "usebackq delims= eol=|" %%F in ("%_EXCL%") do (
set "FILE=%%F"
setlocal EnableDelayedExpansion
echo(!FILE:\=\!
endlocal
)
)
rem // Filter out files that occur in modified exclusion list:
findstr /L /X /V /I /G:"%_TEMP%" "%_LIST%" > "%_FILT%"
rem // Clean up temporary files:
del "%_LIST%" "%_TEMP%"
endlocal
exit /B
如果您的排除列表,比如这次 strictFileNames.txt
,包含纯文件名而不是完整的文件路径,例如,...:[=62=]
restricted.ts excluded.ts [special].ts confidential.ts .config.ts conf.ts
...方法略有不同,因为只考虑文件列表的最后一个路径元素 Files.txt
。为此,您需要在排除列表的每个文件名之前加上一个路径分隔符,同样是一个像 \
这样的转义分隔符,以避免错误匹配;例如,file.ext
将匹配 D:\Data\file.ext
和 D:\Data\X-file.ext
,但 \file.ext
将仅匹配前者,因为 /X
选项已替换为 [=53] =]这次。
这是一个完成该任务的脚本:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\Project\TypeScript" & rem // (path of root directory)
set "_MASK=*.ts" & rem // (file search pattern)
set "_LIST=.\Files.txt" & rem // (path to file list)
set "_EXCL=.\strictFileNames.txt" & rem // (path to exclusion list)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary exclusion list)
set "_FILT=.\tsFiles.txt" & rem // (path to filtered file list)
if not defined _FILT set "_FILT=con"
rem // Generate list of files:
dir /S /B /A:-D "%_ROOT%\%_MASK%" > "%_LIST%"
rem // Modify exclusion list:
rem /* precede every file with an escaped path separator `\`,
rem so no other characters can appear escaped to `findstr`: */
> "%_TEMP%" (
for /F "usebackq delims= eol=|" %%F in ("%_EXCL%") do (
echo(\%%F
)
)
rem // Filter out files that occur in modified exclusion list:
findstr /L /E /V /I /G:"%_TEMP%" "%_LIST%" > "%_FILT%"
rem // Clean up temporary files:
del "%_LIST%" "%_TEMP%"
endlocal
exit /B
选择了以上所有示例文件内容,以便您可以轻松地使用它们并查看使用选项 /X
或 /E
以及加倍路径分隔符时的差异 \
与否。