2011-12-17 14 views
6

मैं बैच फ़ाइल बनाने की कोशिश कर रहा हूं जिसमें अन्य फाइलें उस पर आ सकती हैं। विशेष रूप से, मैं एक हैंडहेल्ड वॉयस रिकॉर्डर द्वारा उत्पादित ऑडियो फ़ाइलों को संपादित करने के लिए ffmpeg का उपयोग कर रहा हूं। समस्या यह है कि ampersands के साथ फ़ाइल नाम का उपयोग करते समय()। इनपुट को उद्धृत करते समय भी, & के बाद कुछ भी गिरा दिया गया है, लेकिन केवल तभी जब फाइलें गिरा दी जाती हैं; यदि फ़ाइल नाम इनपुट कमांड लाइन पर टाइप किया गया है, तो स्क्रिप्ट ठीक काम करती है। cmd विंडो बंद होने से पहले, मैं संक्षेप में फ़ाइल नाम के बाकी हिस्सों को एक त्रुटि के साथ देखता हूं कि यह वैध आदेश के रूप में पहचाना नहीं गया है।"बूंद" बैच स्क्रिप्ट - एम्पर्सेंड युक्त फ़ाइल नाम

यहाँ मेरी स्क्रिप्ट है:

 
rem Change to drive and directory of input file 
%~d1 
cd %~p1 

rem ffmpeg: mix to one channel, double the volume 
%HOMEDRIVE%%HOMEPATH%\ffmpeg.exe -i "%~nx1" -ac 1 -vol 1024 "%~n1 fixed%~x1" 

pause 

यहाँ कमांड लाइन पर दिखने वाली चीज़ों है, "ch17&18.mp3" छोड़ने के बाद:

 
C:\Users\computergeeksjw\Desktop>C:\Users\computergeeksjw\ffmpeg.exe -i "ch17" -ac 1 -vol 1024 "ch17 fixed" 
[...] 
ch17: No such file or directory 

मामले में यह मायने रखती है: मैं Windows 8 डेवलपर पूर्वावलोकन उपयोग कर रहा हूँ। क्या यह मेरी समस्या पैदा कर रहा है? क्या विंडोज 7 या उससे पहले की वही त्रुटि होती है?

उत्तर

13

विंडोज ड्रैग में एक लंबे समय से चलने वाली बग है और फ़ाइल पथों के बारे में कार्यक्षमता ड्रॉप करें जिसमें & या ^ है लेकिन <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 
) 
+0

अद्भुत! बहुत अच्छा काम करता है। यदि यह परेशान नहीं है, तो मुझे स्क्रिप्ट कैसे काम करता है, इस बारे में एक पंक्ति-रेखा-रेखा स्पष्टीकरण पसंद है क्योंकि यह मेरी पहली बैच स्क्रिप्ट है (हालांकि मेरा पहला प्रोग्रामिंग अनुभव नहीं है)। धन्यवाद! – stephenwade

0

मैं चुप भय में डबेंहम के बैच प्रोग्रामिंग कौशल की प्रशंसा करता हूं। मैं उसका समाधान करने की कोशिश की और दोनों समस्याओं कि मैं यहाँ उपस्थित पर ठोकर खाई के रूप में मैं टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है:

  1. वहाँ की लाइन 15 पर पिछले उद्धरण चिह्न के सामने एक अतिरिक्त स्थान हो रहा है उसका बैच टेम्पलेट। मुझे लगता है कि इसे पढ़ने करना चाहिए: नहीं-तो-तारकीय बैच प्रोग्रामिंग ज्ञान के साथ

    set "args=!cmd2:~0,-1!" 
    

    मुझे किसी ने इस तरह की खोज, गंभीर समस्याओं का हो सकता था। मैंने कोशिश की लेकिन बेवकूफ "संपादन कम से कम 6 अक्षर" सीमा के कारण dbenham की पोस्ट को संपादित करने में असमर्थ था।

  2. समाधान आमतौर पर , (अल्पविराम) या ; (सेमीकॉलन) युक्त फ़ाइलों/फ़ोल्डर्स के लिए उपयुक्त नहीं है। यह मामले में काम करने के लिए संशोधित किया जा सकता वहाँ केवल है एक फ़ाइल/फ़ोल्डर लाइन 20 पर उद्धरण में आर्ग बंद करके एक बैच फ़ाइल पर डाला जाता:

    for %%F in ("!args!") do (
    

    जब एक से अधिक फ़ाइल/फ़ोल्डर हटा दिया गया है बैच फ़ाइल पर, मुझे डर है कि विंडोज बग का कोई सामान्य कामकाज संभव नहीं है जो फ़ाइल पथ में अल्पविराम/अर्धविराम से निपट सकता है। विंडोज के SendTo तंत्र में स्पष्ट रूप से एक ही कमी (बग) है, इसलिए ड्रैग-एंड-ड्रॉप बग के आसपास काम करने के लिए उपयोग नहीं किया जा सकता है। इस प्रकार माइक्रोसॉफ्ट तक अंततः इस बग को ठीक करने के लिए है।

संबंधित मुद्दे