विंडोज ड्रैग में एक लंबे समय से चलने वाली बग है और फ़ाइल पथों के बारे में कार्यक्षमता ड्रॉप करें जिसमें &
या ^
है लेकिन <space>
नहीं है।
यदि फ़ाइल पथ में कम से कम एक <space>
है, तो विंडोज स्वचालित रूप से उद्धरणों में पथ संलग्न करता है ताकि इसे ठीक से पार्स किया जा सके। यदि फ़ाइल पथ में &
या ^
है, तो विंडोज़ एक ही काम करना चाहिए, लेकिन ऐसा नहीं है।
यदि आप निम्न सरल बैच फ़ाइल बनाते हैं और उस पर फ़ाइलों को खींचते हैं, तो आप समस्या देख सकते हैं।
@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 . . .
आप देख सकते हैं कि विंडोज नाम में अंतरिक्ष का पता लगाता है और उद्धरण में फ़ाइल encloses मिलता है। फिर कोई समस्या नहीं है।
अब ड्रैग और ड्रॉप "एक & b.txt" और आप
cmd=cmd /c ""C:\test\drag.bat" C:\test\a&b.txt"
%1=C:\test\a
Press any key to continue . . .
विंडोज नाम में कोई रिक्त स्थान नहीं मिल रहा है मिलता है, तो यह उद्धरण में यह बंद नहीं करता है। बड़ी समस्या! विंडोज बैच फ़ाइल में "सी: \ test \ a" पास करता है और बैच फ़ाइल पूर्ण होने के बाद निष्पादित होने वाली दूसरी फ़ाइल के रूप में "b.txt" का व्यवहार करता है। बैच फ़ाइल में हार्ड EXIT कमांड बैच के बाद निष्पादित करने से किसी भी विभाजित फ़ाइल नाम को रोकता है। बेशक b.txt कभी निष्पादित नहीं कर सका। लेकिन अगर फ़ाइल को "& b.bat" और "b.bat" नाम दिया गया था, तो हार्ड एक्सआईटी बैच फ़ाइल में नहीं होने पर यह समस्या हो सकती है।
यह एक बैच फ़ाइल पर एक से अधिक फ़ाइलों खींचें करने के लिए संभव है, और हर एक एक पैरामीटर के रूप में पारित किया जाना चाहिए।
! Cmdcmdline! ड्रैग और ड्रॉप तर्कों को विश्वसनीय रूप से एक्सेस करने का एकमात्र तरीका है। लेकिन अगर बैच फ़ाइल को सामान्य कॉल में सामान्य तर्क के रूप में फाइलें पास की जाती हैं तो यह काम नहीं करेगा।
नीचे एक बैच फ़ाइल है कि अगर यह कहा जाता था और खींचें का उपयोग कर पता लगा सकते हैं एक साधारण कॉल बनाम ड्रॉप है। (यह बुलेट प्रूफ नहीं है, लेकिन मुझे लगता है कि इसे ज्यादातर स्थितियों में काम करना चाहिए) यह कॉल के प्रकार के बावजूद, प्रत्येक फ़ाइल तर्क को एक बार में संसाधित करेगा। (प्रक्रिया केवल फ़ाइल नाम को echos, लेकिन आप जो भी प्रसंस्करण चाहते हैं उसे प्रतिस्थापित कर सकते हैं।) यदि बैच को ड्रैग और ड्रॉप का उपयोग करके बुलाया गया था तो यह विभाजित फ़ाइल नामों के खिलाफ सुरक्षा के लिए एक कठिन निकास करेगा।
@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