&
또는 ^
을 포함하지만 <space>
을 포함하지 않는 파일 경로에 대해서는 Windows의 끌어서 놓기 기능에 오래 문제가 있습니다.
파일 경로에 적어도 하나의 <space>
이 포함되어 있으면 Windows는 자동으로 경로를 따옴표로 묶어 올바르게 구문 분석합니다. 파일 경로에 &
또는 ^
이 포함되어 있으면 Windows에서 동일한 작업을 수행해야하지만 그렇게하지 않아야합니다.
다음 간단한 배치 파일을 만들고 파일을 끌어다 놓으면 문제가 발생합니다.
@echo off
setlocal enableDelayedExpansion
echo cmd=!cmdcmdline!
echo %%1="%~1"
pause
exit
! cmdcmdline! 변수에는 배치 파일을 시작한 실제 명령이 들어 있습니다. 배치 파일은 명령 줄과 첫 번째 매개 변수를 인쇄합니다. 드래그 앤라는 이름의 파일을 삭제하면 당신이 파일 인수 주위에 따옴표가없는 것을 볼 전체 명령 주위에 따옴표를 무시하는 경우
는 "a.txt이"당신은
cmd=cmd /c ""C:\test\drag.bat" C:\test\a.txt"
%1=C:\test\a.txt
Press any key to continue . . .
를 얻을. 특수 문자가 없으므로 아무런 문제가 없습니다.
지금 드래그 "는 b.txt"을 삭제하고 당신은
cmd=cmd /c ""C:\test\drag.bat" "C:\test\a b.txt""
%1="C:\test\a b.txt"
Press any key to continue . . .
당신은 Windows가 이름 공간을 감지하고 따옴표에서 파일을 둘러싸는 방법을 볼 수 있습니다 얻을. 다시 문제는 없습니다.
지금 드래그 "는 & b.txt"을 삭제하고 당신은
cmd=cmd /c ""C:\test\drag.bat" C:\test\a&b.txt"
%1=C:\test\a
Press any key to continue . . .
Windows가 이름에 공간을 검색 할 수 없습니다를 얻을, 그래서 따옴표로 묶어야하지 않습니다. 큰 문제! Windows는 "C : \ test \ a"를 배치 파일에 전달하고 배치 파일이 완료된 후에 실행될 두 번째 파일로 "b.txt"를 처리합니다. 배치 파일의 하드 EXIT 명령은 배치 후에 분할 파일 이름이 실행되지 않도록합니다. 물론 b.txt는 결코 실행될 수 없습니다. 그러나 파일 이름이 "& b.bat"이고 "b.bat"라는 파일이 존재하면 하드 EXIT가 배치 파일에없는 경우 문제가 될 수 있습니다.
배치 파일에 여러 파일을 드래그하여 각 파일을 매개 변수로 전달할 수 있습니다.
! cmdcmdline! 끌어서 놓기 인수에 안정적으로 액세스하는 유일한 방법입니다. 그러나 배치 파일의 정상 호출에서 파일이 일반 인수로 전달되는 경우에는 작동하지 않습니다.
다음은 끌어서 놓기와 일반 호출을 사용하여 호출했는지를 검색 할 수있는 배치 파일입니다. (그것은 총알 증명이 아니지만 대부분의 상황에서 효과가있을 것이라고 생각합니다.) 호출 유형에 관계없이 한 번에 하나씩 각 파일 인수를 처리합니다. 이 프로세스는 단순히 파일 이름을 에코합니다. 그러나 원하는 처리를 대체 할 수 있습니다. 끌어 놓기를 사용하여 일괄 처리를 호출 한 경우 분할 파일 이름을 보호하기 위해 하드 탈출을 수행합니다.
@echo off
setlocal disableDelayedExpansion
::
:: first assume normal call, get args from %*
set args=%*
set "dragDrop="
::
:: Now check if drag&drop situation by looking for %0 in !cmdcmdline!
:: if found then set drag&drop flag and get args from !cmdcmdline!
setlocal enableDelayedExpansion
set "cmd=!cmdcmdline!"
set "cmd2=!cmd:*%~f0=!"
if "!cmd2!" neq "!cmd!" (
set dragDrop=1
set "args=!cmd2:~0,-1! "
set "args=!args:* =!"
)
::
:: Process the args
for %%F in (!args!) do (
if "!!"=="" endlocal & set "dragDrop=%dragDrop%"
rem ------------------------------------------------
rem - Your file processing starts here.
rem - Each file will be processed one at a time
rem - The file path will be in %%F
rem -
echo Process file "%%~F"
rem -
rem - Your file processing ends here
rem -------------------------------------------------
)
::
:: If drag&drop then must do a hard exit to prevent unwanted execution
:: of any split drag&drop filename argument
if defined dragDrop (
pause
exit
)
기존 배치가 하나의 파일 만 처리하도록 설계된 것처럼 보입니다. 여러 파일을 지원하기 위해 호출을 수정해야하는지 여부는 알 수 없습니다. 위의 배치를 수정하여 첫 번째 인수 만 처리하고 인수 처리 루프로 프로세스를 대체했습니다. 이 테스트되지 않은,하지만 그것은 당신을 위해 작동해야한다고 생각합니다.
@echo off
setlocal disableDelayedExpansion
::
:: first assume normal call, get args from %*
set args=%*
set "dragDrop="
::
:: Now check if drag&drop situation by looking for %0 in !cmdcmdline!
:: if found then set drag&drop flag and get args from !cmdcmdline!
setlocal enableDelayedExpansion
set "cmd=!cmdcmdline!"
set "cmd2=!cmd:*%~f0=!"
if "!cmd2!" neq "!cmd!" (
set dragDrop=1
set "args=!cmd2:~0,-1! "
set "args=!args:* =!"
)
::
:: Process the first argument only
for %%F in (!args!) do (
if "!!"=="" endlocal & set "dragDrop=%dragDrop%"
rem ------------------------------------------------
rem - Your file processing starts here.
rem - Use %%F wherever you would normally use %1
rem
rem Change to drive and directory of input file
%%~dF
cd %%~pF
rem ffmpeg: mix to one channel, double the volume
%HOMEDRIVE%%HOMEPATH%\ffmpeg.exe -i "%%~nxF" -ac 1 -vol 1024 "%%~nF fixed%%~xF"
rem
rem - Your file processing ends here
rem -------------------------------------------------
goto :continue
)
:continue
if defined dragDrop (
pause
exit
)
원더풀! 훌륭하게 작동합니다. 귀찮은 일이 아니라면 첫 번째 배치 스크립트이기 때문에 스크립트가 어떻게 작동하는지 한 줄씩 설명하는 것을 좋아할 것입니다 (내 첫 프로그래밍 경험은 아니지만). 감사! – stephenwade