findstr不使用包含短划线( - )的字符串?

时间:2017-03-16 08:22:41

标签: batch-file findstr hyphen

我一直在研究BAT文件,它会根据创建日期删除旧文件。为此,我生成了所有文件和路径的列表,然后是要保护的文件名列表。然后使用FINDSTR从文件和路径列表中删除这些文件。

这个系统运行正常,直到我遇到带破折号的文件(或者看起来好像!)

以下是一个例子:

cleaner_protect.txt包含:

New File.txt 
New File - Copy.txt

cleaner_fullpath.txt包含:

P:\New File.txt
P:\New File - Copy.txt
P:\Old File.txt

我想从cleaner_fullpath.txt中删除存储在cleaner_protect.txt中的新文件,将旧文件留在后面我将删除(不是那个)有点大声笑)。到目前为止,这是我的代码:

:: Remove protected files from list to be deleted (fullpath)
:RemoveFile
:: load string into variable
set /p target= <cleaner_protect.txt
:: remove protected file from full path list
echo -----------------------------
echo Searching for: "%target%"
echo -----------------------------
pause
findstr /v ".\<%target%\>." cleaner_fullpath.txt > cleaner_temp.txt
echo -----------------------------
type cleaner_temp.txt
echo -----------------------------
pause
del cleaner_fullpath.txt
ren cleaner_temp.txt cleaner_fullpath.txt
:: Count remaining lines in list
Set target=cleaner_protect.txt
Set /a lines=0
For /f %%j in ('Find "" /v /c ^< %target%') Do Set /a lines=%%j
Echo %target% has %lines% lines.
pause
:: Loop until completed
IF %lines% GTR 0 (
:: Remove line from protected list
    more +1 cleaner_protect.txt > cleaner_temp.txt
    del cleaner_protect.txt
    ren cleaner_temp.txt cleaner_protect.txt
    set /a lines-=1
    GOTO :RemoveFile
)

暂停和回声用于调试目的......我希望它几乎无形地运行。

有人可以对此有所了解吗?我需要这个代码重复通过一个dropbox并删除可能处于不同结构级别的旧文件。

2 个答案:

答案 0 :(得分:1)

也许这条简单的线条可以满足你的需求:

findstr /E /V /G:cleaner_protect.txt cleaner_fullpath.txt > cleaner_temp.txt

示例输出:

P:\Old File.txt

答案 1 :(得分:0)

我会这样做:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem /* Prepend each line of `cleaner_protect.txt` with `\\`, remove a trailing space,
rem    if applicable, and write result to `cleaner_temp.txt`: */
> "cleaner_temp.txt" (
    for /F "usebackq delims= eol=|" %%E in ("cleaner_protect.txt") do (
        set "ITEM=\\%%E|"
        setlocal EnableDelayedExpansion
        echo !ITEM: ^|=!
        endlocal
    )
)

rem /* Search `cleaner_fullpath.txt` for lines that do not end in any of the lines of
rem    `cleaner_temp.txt` and process the returned items only: */
for /F "delims= eol=|" %%F in ('
    findstr /V /I /E /L /G:"cleaner_temp.txt" "cleaner_fullpath.txt"
') do (
    ECHO del "%%F"
)

rem // Clean up temporary file `cleaner_temp.txt`:
del "cleaner_temp.txt"

endlocal
exit /B

测试完脚本后,删除大写的ECHO命令。

假设cleaner_protect.txt包含此内容:

New File.txt
New File - Copy.txt

临时文件cleaner_temp.txt将包含此内容:

\\New File.txt
\\New File - Copy.txt

拥有文本文件cleaner_fullpath.txt

P:\New File.txt
P:\New File - Copy.txt
P:\Old File.txt

仅处理以下项目:

P:\Old File.txt

前导\\\视为一个文字findstr(因为它使用\作为转义字符。)

实现前缀\\是为了还包括以下情况:

  1. 让我们假设cleaner_protect.txt认为:

    New File.txt
    

    cleaner_fullpath.txt认为:

    P:\New File.txt
    P:\Very New File.txt
    

    如果没有前缀,P:\Very New File.txt最后也会匹配New File.txt,因此不会错误地删除。

  2. 然后让我们假设cleaner_protect.txt认为:

    .File.txt
    

    cleaner_fullpath.txt认为:

    P:\.File.txt
    P:\Other.File.txt
    

    使用\前缀,P:\Other.File.txt最后也会匹配\.File.txt,因为.findstr的元字符(即使是字面搜索)字符串由/L定义,但像\.这样的转义仍然适用并产生文字.),因此它也不会被错误地删除。但是,如果使用\\前缀,则转义适用于第二个\,因此文字\就是结果;使用.选项无需转义/L