2012-05-23 8 views
10

के लिए कस्टम टी कमांड का उपयोग करना मैं बैट फ़ाइल के लिए लिखे गए tee कोड का उपयोग करने का प्रयास कर रहा हूं लेकिन मुझे अपने कोड में इसे लागू करने में समस्या हो रही है। मैं टीई समस्या को हल करने के लिए किसी तीसरे पक्ष के इंस्टॉलेशन का उपयोग नहीं करना चाहता क्योंकि मैं कोड को काम करना चाहता हूं अगर मैं एक वर्ष में अपने कंप्यूटर को प्रारूपित करता हूं और प्रोग्राम को फिर से चलाने के लिए चाहता हूं।.bat फ़ाइल

mycommand.exe | tee.bat -a output.txt 

मैं एक अलग .bat फ़ाइल के साथ की कोशिश की है और साथ कोई लाभ नहीं हुआ एक समारोह (preffered) मूल .bat में के रूप में शामिल की कोशिश की:

मैं इसे इस तरीके से सेटअप

myprogram.exe | call tee -a output.txt 
echo. 
echo. 
echo. 
SET /P restart="Do you want to run again? (1=yes, 2=no): " 
if "%restart%"=="1" GOTO LoopStart 


::-------------------------------------------------------- 
::-- Function section starts below here 
::-------------------------------------------------------- 
:tee 
:: Check Windows version 
IF NOT "%OS%"=="Windows_NT" GOTO Syntax 
| 
:: Keep variables local 
SETLOCAL 

:: Check command line arguments 
SET Append=0 
IF /I [%1]==[-a] (
    SET Append=1 
    SHIFT 
) 
IF  [%1]==[] GOTO Syntax 
IF NOT [%2]==[] GOTO Syntax 

:: Test for invalid wildcards 
SET Counter=0 
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA" 
IF %Counter% GTR 1 (
    SET Counter= 
    GOTO Syntax 
) 

:: A valid filename seems to have been specified 
SET File=%1 

:: Check if a directory with the specified name exists 
DIR /AD %File% >NUL 2>NUL 
IF NOT ERRORLEVEL 1 (
    SET File= 
    GOTO Syntax 
) 

:: Specify /Y switch for Windows 2000/XP COPY command 
SET Y= 
VER | FIND "Windows NT" > NUL 
IF ERRORLEVEL 1 SET Y=/Y 

:: Flush existing file or create new one if -a wasn't specified 
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1) 

:: Actual TEE 
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
    > CON ECHO.%%B 
    >> %File% ECHO.%%B 
) 

:: Done 
ENDLOCAL 
GOTO:EOF 


:Count 
SET /A Counter += 1 
SET File=%1 
GOTO:EOF 


:Syntax 
ECHO. 
ECHO Tee.bat, Version 2.11a for Windows NT 4/2000/XP 
ECHO Display text on screen and redirect it to a file simultaneously 
ECHO. 
IF NOT "%OS%"=="Windows_NT" ECHO Usage: some_command ¦ TEE.BAT [ -a ] filename 
IF NOT "%OS%"=="Windows_NT" GOTO Skip 
ECHO Usage: some_command ^| TEE.BAT [ -a ] filename 
:Skip 
ECHO. 
ECHO Where: "some_command" is the command whose output should be redirected 
ECHO   "filename"  is the file the output should be redirected to 
ECHO   -a    appends the output of the command to the file, 
ECHO      rather than overwriting the file 
ECHO. 
ECHO Written by Rob van der Woude 
ECHO http://www.robvanderwoude.com 
ECHO Modified by Kees Couprie 
ECHO http://kees.couprie.org 
ECHO and Andrew Cameron 

मैं आउटपुट को विभाजित करने की कोशिश कर रहा हूं ताकि मैं कंसोल आउटपुट को फ़ाइल में सहेज सकूं जबकि अभी भी चल रहे प्रोग्राम के साथ बातचीत करने में सक्षम हो।

मैं टीई कमांड को अपने .bat के साथ ठीक से काम करने के लिए कैसे प्राप्त कर सकता हूं ताकि मैं आउटपुट को एक फ़ाइल और कंसोल दोनों में विभाजित कर सकूं।

+0

एचएम, यह मेरे लिए काम करता है। क्या आप सुनिश्चित हैं कि 'mycommand.exe' stdout को आउटपुट करता है, stderr नहीं? बाद वाले को कैप्चर करने के लिए, आपको 'mycommand.exe 2> और 1 | की आवश्यकता होगी कॉल टी ... ' –

उत्तर

18

एक पाइप के भीतर बैच फ़ंक्शन को कॉल करने का आपका प्रयास हमेशा विंडोज़ पाइप काम करने के कारण विफल रहता है - विंडोज नए सीएमडी गोले के माध्यम से पाइप के दोनों तरफ तत्काल करता है। अधिक जानकारी के लिए https://stackoverflow.com/a/8194279/1012053 देखें।

बैच टी के रॉब वैन डेर वाउडे संस्करण संभवतः आपके लिए काम नहीं कर सकते हैं क्योंकि यह कमांड के परिणामों को पढ़ने के लिए FOR /F का उपयोग करता है - कमांड को पढ़ने से पहले कमांड को पूरा करने के लिए निष्पादित करना होगा। अगर आपको कमांड के निष्पादन के दौरान उपयोगकर्ता इंटरैक्शन की आवश्यकता होती है तो यह काम नहीं करेगा। टी के उस संस्करण के साथ आप फ़ाइल को आउटपुट पर रीडायरेक्ट कर सकते हैं और फिर TYPE फ़ाइल समाप्त होने पर भी हो सकता है। जाहिर है कि आप क्या चाहते हैं।

शुद्ध बैच चालें हैं जो आपको करीब ले सकती हैं, लेकिन मुझे लगता है कि अभी भी एक समस्या है जिसे शुद्ध बैच के साथ हल नहीं किया जा सकता है। आपका निष्पादन योग्य एक नई लाइन जारी किए बिना एक लाइन पर एक संकेत डाल सकता है। मेरा मानना ​​है कि शुद्ध देशी बैच हमेशा पूरी लाइनें पढ़ता है (धारा के अंत में छोड़कर)। मुझे चरित्र द्वारा चरित्र पढ़ने के लिए बैच विधि से अवगत नहीं है।

थोड़ा सा सुधार-SET /P पाइप इनपुट का आंशिक लाइनों पढ़ सकते हैं, लेकिन यह सीमाओं है कि यह एक मजबूत बैच टी समाधान के लिए इस्तेमाल किया जा रहा से रोकने के होते हैं: कोई रास्ता नहीं निश्चित रूप से जानना है जब प्रत्येक पंक्ति समाप्त होता है । यह प्रति "लाइन" के लिए 1021 वर्णों तक सीमित है। यह प्रत्येक "रेखा" के अंत से नियंत्रण वर्णों को स्ट्रिप्स करता है। इनपुट स्ट्रीम के अंत तक पहुंचने के बारे में बताने का कोई तरीका नहीं है।

लेकिन एक आसान समाधान है - जेस्क्रिप्ट या वीबीस्क्रिप्ट एक चैंप की तरह काम करता है, और किसी विशेष इंस्टॉल की आवश्यकता नहीं होती है। यहां एक संकर जेस्क्रिप्ट/बैच स्क्रिप्ट है जो आपके लिए काम करनी चाहिए। सुधार के लिए बहुत सारे कमरे के साथ जेस्क्रिप्ट खराब लिखा गया है। उदाहरण के लिए, कोई त्रुटि जांच नहीं है।

मैं स्क्रिप्ट को tee.bat के रूप में सहेजता हूं। पहला आवश्यक तर्क फ़ाइल के नाम को लिखने के लिए निर्दिष्ट करता है। डिफ़ॉल्ट रूप से, फ़ाइल पहले से लिखी गई है यदि यह पहले से मौजूद है। यदि कोई दूसरा तर्क प्रदान किया जाता है (मान कोई फर्क नहीं पड़ता), तो आउटपुट को इसके बजाय फ़ाइल में जोड़ा जाता है।

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment 

::--- Batch section within JScript comment that calls the internal JScript ---- 
@echo off 
cscript //E:JScript //nologo "%~f0" %* 
exit /b 

----- End of JScript comment, beginning of normal JScript ------------------*/ 
var fso = new ActiveXObject("Scripting.FileSystemObject"); 
var mode=2; 
if (WScript.Arguments.Count()==2) {mode=8;} 
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true); 
var chr; 
while(!WScript.StdIn.AtEndOfStream) { 
    chr=WScript.StdIn.Read(1); 
    WScript.StdOut.Write(chr); 
    out.Write(chr); 
} 

उपयोग की अपेक्षा बहुत अधिक है।

command.exe | tee.bat output.txt 1 

पिछले 1 तर्क बलों मोड जोड़ देते हैं। यह 1

के अलावा कोई भी मूल्य हो सकता है जैसा कि आप पसंद करते हैं, सब कुछ एक बैच स्क्रिप्ट में रखना संभव है।

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment 

::--- Batch section within JScript comment ---------------------------- 
@echo off 

::This block of code handles the TEE by calling the internal JScript code 
if "%~1"=="_TEE_" (
    cscript //E:JScript //nologo "%~f0" %2 %3 
    exit /b 
) 

::The rest of your batch script goes here 

::This pipes to TEE in append mode 
mycommand.exe | "%~f0" _TEE_ output.txt 1 

exit /b 

----- End of JScript comment, beginning of normal JScript ------------------*/ 
var fso = new ActiveXObject("Scripting.FileSystemObject"); 
var mode=2; 
if (WScript.Arguments.Count()==2) {mode=8;} 
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true); 
var chr; 
while(!WScript.StdIn.AtEndOfStream) { 
    chr=WScript.StdIn.Read(1); 
    WScript.StdOut.Write(chr); 
    out.Write(chr); 
} 

अद्यतन

बैच पटकथा में एक अकादमिक रुचि रखने वाले व्यक्ति के लिए, मैं Asynchronous native batch tee script से अधिक DosTips पर पर टी का एक शुद्ध देशी बैच संस्करण पोस्ट किया है। लेकिन यह संकर दृष्टिकोण मेरा पसंदीदा स्क्रिप्टिंग समाधान है।

+1

+1, अच्छा, केवल भाग 'मेरा मानना ​​है कि शुद्ध देशी बैच हमेशा पूरी लाइनें पढ़ता है' गलत है, मैं इसे कुछ _multithreading_ batches में उपयोग करता हूं – jeb

+2

@jeb - मुझे और दिखाएं! मेरे साथ षड्यंत्र रचा गया। – dbenham

+1

यह पूरी तरह से काम करता है !! बहुत बहुत धन्यवाद, अगर मैं कर सकता तो मैं 5 बार वोट दूंगा। उत्तर और टिप्पणी पर – Nick

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