您可以使用for /f
將文件名拆分爲_
分隔符處的兩個標記。您不需要包含.txt
分機號,因此您需要拆分%%~nA
而不是%%A
。
你可以使用dir
與findstr
,以驗證該文件名具有有效的格式,並改變外for
環路for /f
來處理這一結果。例如,您不想處理看起來像"vendor_.txt"
的文件名。我的findstr
命令驗證只有一個_
,並且前後至少有一個非下劃線字符。
有人會認爲,以下將工作
@echo off
:: This does not work - each line of input to java has an unwanted trailing space
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_ tokens=1*" %%B in ("%%~nA") do (
echo %%A
echo %%B
echo %%C
) | java -jar c:\generator.jar
但有一個陰險的問題,是由於該管的每一側在新的cmd.exe進程執行的事實。必須解析管道的每一側並將其打包成cmd /c ....
命令。左側最終看起來像這樣:
C:\Windows\system32\cmd.exe /S /D /C"echo fileName &echo vendor &echo model "
,
在每行的末尾有一個不需要的空間。像(echo %%A)
添加括號不起作用。
如果任何文件名包含像&
這樣的毒性字符,還有另一個潛在的問題。如果您的供應商名稱是「Bell & Howell」,則左側過程將嘗試執行
echo Bell&Howell
。 「貝爾」會適當地回聲,但「豪厄爾」將被解釋爲一個命令,幾乎肯定會失敗並出現錯誤,但在任何情況下都不會產生期望的結果。
請參閱Why does delayed expansion fail when inside a piped block of code?瞭解有關管道潛在問題的更多信息,以及處理這些問題的策略。
下面是我應該解決問題的原始代碼的增強。我通過將字符串文字放在引號內解決了有毒字符問題,然後使用在cmd.exe子進程中執行的for
語句在ECHOing該值之前安全地剝離引號。
我通過使用%%echoX%%
「宏」延遲解析命令來解決不必要的尾部空間問題。雙倍百分比延遲「宏觀」的擴展直到我們進入子進程之後。
@echo off
setlocal disableDelayedExpansion
:: This echoX "macro" delays parsing of the echo command to avoid the unwanted trailing space
set "echoX=(echo %%~X)"
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
(for %%X in ("%%~A" "%%B" "%%C") do @%%echoX%%) | java -jar c:\generator.jar
)
另一種選擇是,以限定多行變量嵌入換行符,然後使用CMD/V:ON,以使在子進程延遲擴展。
@echo off
setlocal disableDelayedExpansion
for %%L in (^"^
%= This creates a quoted linefeed character in the FOR variable L =%
^") do for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
set "str=%%A%%~L%%B%%~L%%C"
cmd /v:on /c "(echo !str!)" | java -jar c:\generator.jar
)
這是一個更簡單的替代方案,它使用臨時文件而不是管道。它避免了管道可能出現的許多問題。
@echo off
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
>temp.txt (
(echo %%~A)
(echo %%B)
(echo %%C)
)
<temp.txt java -jar c:\generator.jar
del temp.txt
)
'用於%%一個在(的 「* .txt」)做/ F 「有usebackq令牌= 1-3 delims = _ EOL = _」 %% b在( 「%%〜a」)的做((echo/%% b&echo/%% c&echo/%% d)| java -jar C:\ Generator.jar)' – aschipfl
@aschipfl - 您使用'usebackq'需要'in('%%〜a') '。另外,第一個輸入是整個文件名,而不是從名稱解析的值。但最糟糕的是,每一行輸入到java將有一個不需要的尾隨空間。看到[我的回答](https://stackoverflow.com/a/44927438/1012053) – dbenham
@dbenham,我誤解了這個問題,並認爲供應商的名稱和型號是文本文件的內容而不是他們的名字;這就是爲什麼我使用'usebackq'。對於尾隨空間你是對的,我的評論只是一個快速的拍攝,我沒有真正考慮過它們。順便說一句,很好的答案! – aschipfl