2017-04-16 23 views
1

私はディレクトリを通過し、そのディレクトリ内のすべてのファイルにffmpegコマンドを実行するforループを作成しようとしています。私の問題は、遅延拡張を使用するときに問題の原因となるファイルの一部に、名前に!が含まれていることです。私は多くのソリューションを研究しており、誰も私をどこにでも連れて来ない。現在、!が含まれているファイル名をエコー表示できますが、!のファイル名をforループに渡すことはできません。遅延拡張によって効果的に!が削除されます。バッチファイル:Escaping! 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%" 

それから私は、ファイル名と完全なパスが含ま!でエコーするために得ることができますが、%fname%%fpath%を参照ffmpegのコマンドはNo such file or directoryメッセージを返します。エコーをオフにした直後にSetLocal EnableDelayedExpansionを追加し、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交換可能なパラメータから取得した情報を割り当てるする必要は `%のFPATH%は`引用符で囲む必要があるため、単にあなたの問題が解決しない検索された値

+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% ''となります。私にとって興味深いのは、あなたの答えは 'DisableDelayedExpansion'で追加したものとはちょっと違っていますが、それはそれが必要ではないことが分かります。 '%fpath%'を引用符で囲むだけで動作させることができます。問題が解決しました! – Trevor

0

私はあまりにも早く投稿しました!私はついにそれを働かせました!

ffmpeg入力に%fpath%を使用している2番目のスクリプトでは、(引用符で囲まれていないため)切り詰めた最初のスペースまでファイルパスを取得するだけです。 %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は引用符で囲まれた '^'を '^^'に二重にし、コマンドは失敗します。遅延された展開、CALL、適切に引用された引数はありません[MC NDには正解があります](http://stackoverflow.com/a/43435510/1012053)。 – dbenham

関連する問題