2012-03-16 118 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