2017-04-16 61 views
1

我正在嘗試創建一個for循環,它將通過一個目錄並對該目錄中的所有文件運行ffmpeg命令。我的問題是某些文件的名稱中有!,這在使用延遲擴展時會導致問題。我研究了許多解決方案,其中沒有一個能夠讓我找到任何地方。目前我可以使用包含的!來回顯文件名,但我似乎無法通過!將文件名傳遞到我的for循環中,因爲延遲擴展有效地刪除了!批處理文件:轉義!在For循環中

這裏是我的批處理腳本:

@echo off 
setlocal enabledelayedexpansion 
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
    set "filename=%%~nxf" 
    ffmpeg -i "%%f" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\!filename!" 
) 
pause 

這對所有文件工作正常,沒有在名稱中!。如果我使用批處理腳本是這樣的:

@echo off 
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
    call :command "%%f" 
) 
pause 

:command 
set "fname=%~nx1" 
set "fpath=%~dpnx1" 
echo %fname% 
ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%" 

然後,我可以得到的文件名和完整路徑與包括!呼應,但ffmpeg的命令引用%fname%%fpath%返回No such file or directory消息。如果我在SetLocal EnableDelayedExpansion之後加上echo off並將ffmpeg字符串更改爲!而不是%,那麼我將再次獲得No such file or directory消息。

我知道,在聲明的DO部分FOR環路一切都得到一切這就是爲什麼我需要使用延遲擴展前擴大,但我該如何使用,並仍在使用包含!文件名?有沒有辦法讓第一批接受名稱中包含!的文件?

回答

5

最簡單的解決方案是不使用延遲擴展。

@echo off 
    setlocal enableextensions disabledelayedexpansion 
    set ffmpegArguments=-vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 

    for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
     ffmpeg -i "%%f" %ffmpegArguments% "E:\Converted\%%~nxf" 
    ) 
    pause 

沒有任何需要分配從for替換參數變量檢索到的信息,只需使用檢索到的值

+0

你忘了提及沒有需要CALL。 CALL會破壞包含'^'的任何名稱。你的代碼應該適用於所有情況。 – dbenham

+0

出色的工作MC ND!這很簡單,後見之明很有意義! – Trevor

0
:command 

SETLOCAL DISABLEDELAYEDEXPANSION 

set "fname=%~nx1" 
set "fpath=%~dpnx1" 
echo %fname% 
ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%" 

ENDLOCAL 
GOTO :EOF 

應通過禁用delayedexpansion而!是文字字符解決您的問題。

我加了goto出於習慣,所以如果我添加一個新的子程序,我不必記住它。

+0

您的不起作用,因爲'%fpath%'需要加引號,''%fpath%「'。對我來說有趣的是,你的答案與我在'DisableDelayedExpansion'中添加的內容不同,但事實證明它甚至不需要。我只需將'%fpath%'放在引號中即可。問題解決了! – Trevor

0

我發帖太快了!我終於搞定了!

事實證明,在使用%fpath%的第二個腳本中,ffmpeg輸入只獲取文件路徑,直到它截斷的第一個空間(因爲我沒有用引號括起來)。將%fpath%放在引號中後,該腳本將使用名稱中包含!的文件!這是它:

@echo off 
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
    call :command "%%f" 
) 

:command 
set "fname=%~nx1" 
set "fpath=%~dpnx1" 
ffmpeg -i "%fpath%" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%" 
+0

你設法修復你的代碼,但我不認爲你完全理解爲什麼。是的,你必須引用'「%fpath%」',但是當你的FOR循環展開'%% f'時,如果該值可能包含'!',那麼延遲擴展也是關鍵的。默認是禁用延遲擴展,但您的原始代碼已啓用。此答案中的代碼可用,因爲您不啓用延遲擴展。 – dbenham

+1

你仍然有失敗的可能性。如果文件路徑包含'^'字符,則CALL會將引用的^ ^加倍到'^^',並且您的命令將失敗。 [MC ND有一個正確的答案](http://stackoverflow.com/a/43435510/1012053)應該在所有情況下工作 - 沒有延遲擴展,沒有CALL和正確引用的參數。 – dbenham