2012-03-16 112 views
0

我想工作了一个批处理文件来在一行文字的两块结合第一线上结合两段文本。第一个是文件名;二是文本的第一行开头“为:”。我一直在挣扎几个小时,这是我得到的:批次 - 在一个循环

@echo off 
IF EXIST fullnames.txt DEL fullnames.txt 
FOR /F %%g IN ('dir /b *.eml') DO (
SET filename=%~f1 
SET toline=FINDSTR /B /C "To: " 
ECHO %FILENAME%%TOLINE% >> fullnames.txt 
) 

它不起作用。我得到的错误或不正确的结果几乎不管什么我放下手中的文件名行;甚至还没有开始测试手提包的一部分。有什么建议么?

回答

0

您不能分配和使用环境变量里面一个for循环。使用延迟变量扩展或调用子例程。

延迟会是这个样子

setlocal EnableDelayedExpansion 

    @echo off 
    IF EXIST fullnames.txt DEL fullnames.txt 
    FOR /F %%g IN ('dir /b *.eml') DO (
    SET filename=%~f1 
    SET toline=FINDSTR /B /C "To: " 
    ECHO !FILENAME!!TOLINE! >> fullnames.txt 
    ) 

然而,这看起来并不像它会正常工作呢。我会这样做

FOR /F %%g IN ('dir /b *.eml') DO call :process %%g 
    goto :eof 

    :process 
    SET filename=%~f1 
    SET toline=FINDSTR /B /C "To: " 
    ECHO %FILENAME%%TOLINE% >> fullnames.txt 
+0

但是'设置toline = FINDSTR/B/C“为:”'不会_execute_了' FINDSTR'命令,它仅分配文本 – jeb 2012-03-17 06:05:19

2

您已经使用FOR/F来捕获DIR命令的输出。捕捉FINDSTR的输出是没有什么不同。

但是,使用简单的FOR代替DIR命令的FOR/F会更高效。

您使用%~f1当我想你打算%%~fg

您不能使用%var%扩展括号内的变量集,您必须使用!var!反而延迟扩展。在命令行中键入SET /?了解更多信息 - 阅读开始节“最后,对于延迟的环境变量扩展支持已经 添加...”

然而,在你的情况,你可以很容易地避免使用延迟扩展(不是它是一个问题)。

而不是删除任何现有的“fullnames.txt”,然后将输出附加到它,更有效的方法是将整个结构放在括号内,并使用over-write模式将所有输出重定向到文件。

@echo off 
(
    for %%F in (*.eml) do (
    for "delims=" %%A in ('findstr /b /c:"To: " "%%F"') do echo %%F %%A 
) 
) >fullnames.txt 

但是,上面的解决方案虽然简单,但它比需要的复杂得多。

FINDSTR可以处理使用通配符指定的多个文件,并且它会将每个匹配行与文件名后跟一个冒号前缀。

您可以通过命令行让你的结果只是甚至没有使用批处理文件(或者你可以把这个批处理文件):

findstr /b /c:"To: " *.eml >fullnames.txt 

编辑
如果您关注的是,文件可能包含多行开始“为:”,你只需要使用的第一行,那么就回使用批处理文件:

@echo off 
setlocal enableDelayedExpansion 
set "prevFile=" 
(
    for /f "tokens=1* delims=:" %%A in ('findstr /b /c:"To: " *.eml') do (
    if "%%A" neq "!prevFile!" echo %%A: %%B 
    set "prevFile=%%A" 
) 
) >fullnames.txt 

上述解决方案可以˚F如果文件名包含!。此外,只要路径不包含驱动器号,路径可以与*.eml一起使用。驱动器和!问题都可以通过其他修改来解决。

2
@echo off 
setlocal EnableDelayedExpansion 
if exist fullnames.txt del fullnames.txt 
for %%f in (*.eml) do (
    set toline= 
    for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
     if not defined toline set "toline=%%l" 
    ) 
    echo %%f!toline! >> fullnames.txt 
) 

EDIT简单的方法加入

set toline=命令删除“toline”变量处理每个文件之前,所以只在第一“到:”中找不到匹配的线被分配给它,并稍后使用延迟扩展显示。然而,这个过程可以在不需要延迟扩展更简单的方式来实现,如dbenham建议:

@echo off 
if exist fullnames.txt del fullnames.txt 
for %%f in (*.eml) do (
    set firstFind= 
    for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
     if not defined firstFind set firstFind=now & echo %%f%%l >> fullnames.txt 
    ) 
) 
+0

尝试仅处理第一个“To:”行被窃听。另外,不需要延迟扩展。在内部循环中:'如果没有定义toline set toline = 1&echo %% f %% l >> fullnames.txt' – dbenham 2012-03-17 13:11:44

+0

@dbenham:为什么说第一个“To:”行的过程是被窃听的? – Aacini 2012-03-18 14:35:05

+0

对不起,Aacini,我的一个愚蠢的错误。代码完美工作。 – dbenham 2012-03-18 14:54:13