ฉันมีสคริปต์ชุดงานที่ดำเนินการงานและส่งผลลัพธ์ไปยังไฟล์ข้อความ มีวิธีให้เอาต์พุตแสดงบนหน้าต่างคอนโซลด้วยหรือไม่?
ตัวอย่างเช่น:
c:\Windows>dir > windows-dir.txt
มีวิธีการdir
แสดงผลในหน้าต่างคอนโซลและใส่ลงในไฟล์ข้อความหรือไม่?
ฉันมีสคริปต์ชุดงานที่ดำเนินการงานและส่งผลลัพธ์ไปยังไฟล์ข้อความ มีวิธีให้เอาต์พุตแสดงบนหน้าต่างคอนโซลด้วยหรือไม่?
ตัวอย่างเช่น:
c:\Windows>dir > windows-dir.txt
มีวิธีการdir
แสดงผลในหน้าต่างคอนโซลและใส่ลงในไฟล์ข้อความหรือไม่?
คำตอบ:
ไม่คุณไม่สามารถเปลี่ยนเส้นทางได้อย่างแท้จริง
แต่ด้วยเทคนิคบางอย่าง (เช่นtee.bat ) คุณสามารถทำได้
ฉันพยายามอธิบายการเปลี่ยนเส้นทางสักหน่อย
คุณเปลี่ยนเส้นทางหนึ่งในสิบสตรีมด้วย> fileหรือ<file
ซึ่งไม่สำคัญหากการเปลี่ยนเส้นทางอยู่ก่อนหรือหลังคำสั่งดังนั้นทั้งสองบรรทัดจึงใกล้เคียงกัน
dir > file.txt
> file.txt dir
การเปลี่ยนเส้นทางในตัวอย่างนี้เป็นเพียงทางลัดสำหรับ1>ซึ่งหมายความว่าสตรีม 1 (STDOUT) จะถูกเปลี่ยนเส้นทาง
ดังนั้นคุณสามารถเปลี่ยนเส้นทางสตรีมใดก็ได้โดยใส่หมายเลขไว้ล่วงหน้าเช่น2> err.txtและยังได้รับอนุญาตให้เปลี่ยนเส้นทางสตรีมหลายรายการในบรรทัดเดียว
dir 1> files.txt 2> err.txt 3> nothing.txt
ในตัวอย่างนี้ "เอาต์พุตมาตรฐาน" จะเข้าสู่ files.txt ข้อผิดพลาดทั้งหมดจะอยู่ใน err.txt และ stream3 จะกลายเป็น nothing.txt (DIR ไม่ใช้สตรีม 3)
Stream0 คือ STDIN
Stream1 คือ STDOUT
Stream2 คือ STDERR
Stream3-9 ไม่ได้ใช้
แต่จะเกิดอะไรขึ้นหากคุณพยายามเปลี่ยนเส้นทางสตรีมเดียวกันหลาย ๆ ครั้ง
dir > files.txt > two.txt
"มีได้เพียงหนึ่งเดียว" และสุดท้ายเสมอ!
มันจึงเท่ากับdir> two.txt
โอเคมีความเป็นไปได้พิเศษอย่างหนึ่งคือเปลี่ยนเส้นทางสตรีมไปยังสตรีมอื่น
dir 1>files.txt 2>&1
2> & 1การเปลี่ยนเส้นทางไป stream2 stream1 และ1> files.txtเปลี่ยนเส้นทางทั้งหมดเพื่อfiles.txt
คำสั่งมีความสำคัญที่นี่!
dir ... 1>nul 2>&1
dir ... 2>&1 1>nul
แตกต่าง. บรรทัดแรกเปลี่ยนเส้นทางทั้งหมด (STDOUT และ STDERR) ไปยัง NUL
แต่บรรทัดที่สองเปลี่ยนเส้นทาง STDOUT เป็น NUL และ STDERR ไปยัง STDOUT "ว่าง"
สรุปได้ชัดเจนว่าเหตุใดตัวอย่างของOtávioDécioและ andynormancx จึงไม่สามารถใช้งานได้
command > file >&1
dir > file.txt >&2
ทั้งสองพยายามเปลี่ยนเส้นทาง stream1 สองครั้ง แต่ "มีได้เพียงครั้งเดียว" และเป็นครั้งสุดท้ายเสมอ
คุณจะได้รับ
command 1>&1
dir 1>&2
และในตัวอย่างแรกไม่อนุญาตให้เปลี่ยนเส้นทาง stream1 ไปยัง stream1 (และไม่มีประโยชน์มากนัก)
หวังว่าจะช่วยได้
3<&2
(หมายเหตุ LT แทน GT) 3>errors.txt
และจากนั้น แต่สิ่งนี้จบลงอย่างไม่ดี - เอาต์พุต stderr ที่ตามมาทั้งหมดถูกจับไปที่errors.txt
(นั่นคือ - จากคำสั่งอื่นด้วย!)
เพียงใช้คำสั่ง UNIX tee เวอร์ชัน Windows (พบจากhttp://unxutils.sourceforge.net ) ด้วยวิธีนี้:
mycommand > tee outpu_file.txt
หากคุณต้องการเอาต์พุต STDERR ด้วยให้ใช้สิ่งต่อไปนี้ รวมการส่งออก STDERR ลง STDOUT (กระแสหลัก)2>&1
mycommand 2>&1 | tee output_file.txt
1>tee a.txt
จะเปลี่ยนเส้นทาง stdout ไปยังไฟล์ที่มีชื่อtee
แทนที่จะเรียกtee
คำสั่ง มีใครยืนยันได้ไหมว่าคำตอบนี้เหมาะกับพวกเขา
หากคุณไม่ต้องการผลลัพธ์แบบเรียลไทม์ (เช่นขณะที่โปรแกรมกำลังเขียน) คุณสามารถเพิ่มได้
type windows-dir.txt
หลังจากบรรทัดนั้น
dir > windows-dir.txt & type windows-dir.txt
(มีประโยชน์ที่พร้อมท์): ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt
นี้ยังใช้กับบล็อก: อย่างไรก็ตามหากต้องการเอาต์พุตแบบเรียลไทม์คุณสามารถใช้เช่นพอร์ต windows ของเครื่องมือทีสำหรับสิ่งนั้น ...
วิธีแก้ปัญหาที่ใช้ได้ผลสำหรับฉันคือ: dir> a.txt | ประเภท a.txt
ใช่มีวิธีแสดงเอาต์พุตคำสั่งเดียวบนคอนโซล (หน้าจอ) และในไฟล์ โดยใช้ตัวอย่างของคุณใช้ ...
@ECHO OFF
FOR /F "tokens=*" %%I IN ('DIR') DO ECHO %%I & ECHO %%I>>windows-dir.txt
คำอธิบายโดยละเอียด:
FOR
คำสั่งแยกวิเคราะห์ผลลัพธ์ของคำสั่งหรือข้อความลงในตัวแปรซึ่งสามารถอ้างอิงหลายครั้ง
สำหรับคำสั่งเช่นDIR /B
ใส่เครื่องหมายคำพูดเดี่ยวตามที่แสดงในตัวอย่างด้านล่าง แทนที่DIR /B
ข้อความด้วยคำสั่งที่คุณต้องการ
FOR /F "tokens=*" %%I IN ('DIR /B') DO ECHO %%I & ECHO %%I>>FILE.TXT
สำหรับการแสดงข้อความให้ใส่ข้อความในเครื่องหมายคำพูดคู่ดังที่แสดงในตัวอย่างด้านล่าง
FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO ECHO %%I & ECHO %%I>>FILE.TXT
... และด้วยการพันเส้น ...
FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO (
ECHO %%I & ECHO %%I>>FILE.TXT
)
ถ้าคุณมีครั้งเมื่อคุณต้องการส่งออกเฉพาะบนคอนโซล (หน้าจอ) และครั้งอื่น ๆ ที่ส่งไปยังไฟล์และครั้งอื่น ๆ ที่ส่งทั้งระบุ "DO" %TOECHOWHERE%
ประโยคของใช้สำหรับวงตัวแปรตามที่แสดงด้านล่างด้วย
@ECHO OFF
FOR %%I IN (TRUE FALSE) DO (
FOR %%J IN (TRUE FALSE) DO (
SET TOSCREEN=%%I & SET TOFILE=%%J & CALL :Runit)
)
GOTO :Finish
:Runit
REM Both TOSCREEN and TOFILE get assigned a trailing space in the FOR loops
REM above when the FOR loops are evaluating the first item in the list,
REM "TRUE". So, the first value of TOSCREEN is "TRUE " (with a trailing
REM space), the second value is "FALSE" (no trailing or leading space).
REM Adding the ": =" text after "TOSCREEN" tells the command processor to
REM remove all spaces from the value in the "TOSCREEN" variable.
IF "%TOSCREEN: =%"=="TRUE" (
IF "%TOFILE: =%"=="TRUE" (
SET TEXT=On screen, and in "FILE.TXT"
SET TOECHOWHERE="ECHO %%I & ECHO %%I>>FILE.TXT"
) ELSE (
SET TEXT=On screen, not in "FILE.TXT"
SET TOECHOWHERE="ECHO %%I"
)
) ELSE (
IF "%TOFILE: =%"=="TRUE" (
SET TEXT=Not on screen, but in "FILE.TXT"
SET TOECHOWHERE="ECHO %%I>>FILE.txt"
) ELSE (
SET TEXT=Not on screen, nor in "FILE.TXT"
SET TOECHOWHERE="ECHO %%I>NUL"
)
)
FOR /F "tokens=*" %%I IN ("%TEXT%") DO %TOECHOWHERE:~1,-1%
GOTO :eof
:Finish
ECHO Finished [this text to console (screen) only].
PAUSE
delims=
แทน
command > file >&1
หากคุณต้องการต่อท้ายแทนการแทนที่ไฟล์ผลลัพธ์คุณอาจต้องการใช้
dir 1>> files.txt 2>> err.txt
หรือ
dir 1>> files.txt 2>>&1
ตัวเลือกของฉันคือ:
สร้างรูทีนย่อยที่รับข้อความและทำให้กระบวนการส่งไปยังคอนโซลและล็อกไฟล์โดยอัตโนมัติ
setlocal
set logfile=logfile.log
call :screenandlog "%DATE% %TIME% This message goes to the screen and to the log"
goto :eof
:screenandlog
set message=%~1
echo %message% & echo %message% >> %logfile%
exit /b
หากคุณเพิ่มตัวแปรลงในข้อความอย่าลืมลบเครื่องหมายคำพูดในนั้นออกก่อนที่จะส่งไปยังรูทีนย่อยมิฉะนั้นจะทำให้แบตช์ของคุณเสียหายได้ แน่นอนว่าสิ่งนี้ใช้ได้กับการสะท้อนเท่านั้น
setlocal enabledelayedexpansion
แทนแค่setlocal
2)ฉันใช้การขยายล่าช้าสำหรับตัวแปร logfile ดังนั้น>> !logfile!
แทนที่จะใช้>> %logfile%
ภายในรูทีนย่อย วิธีนี้จะทำงานเมื่อถูกเรียกจากภายในบล็อกรหัส (เช่นภายในคำสั่ง if) 3)ฉันลบบรรทัด "set message" ออกเพราะไม่จำเป็นต้องใช้ตัวแปรเพิ่มเติม เรามีมันอยู่แล้ว$~1
ดังนั้นฉันจึงมีecho $~1
ทั้งคำสั่ง echo
ฉันสร้างคอนโซล C # ง่ายๆซึ่งสามารถจัดการเอาต์พุตแบบเรียลไทม์ไปยังทั้งหน้าจอ cmd และบันทึก
class Tee
{
static int Main(string[] args)
{
try
{
string logFilePath = Path.GetFullPath(args[0]);
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
for (int value; (value = Console.In.Read()) != -1;)
{
var word = Char.ConvertFromUtf32(value);
Console.Write(word);
writer.Write(word);
}
}
}
catch (Exception)
{
return 1;
}
return 0;
}
}
การใช้งานไฟล์แบตช์จะเหมือนกับวิธีที่คุณใช้ Unix tee
foo | tee xxx.log
และนี่คือที่เก็บซึ่งรวมถึง Tee.exe ในกรณีที่คุณไม่มีเครื่องมือในการรวบรวม https://github.com/iamshiao/Tee
ฉันชอบคำตอบของ atn แต่มันก็ไม่ได้เป็นเรื่องเล็กน้อยสำหรับฉันที่จะดาวน์โหลดเป็นwinteeซึ่งเป็นโอเพ่นซอร์สและให้ฟังก์ชันทีเท่านั้น (มีประโยชน์หากคุณต้องการเพียงแค่ทีและไม่ใช่ยูทิลิตี้ยูนิกซ์ทั้งชุด) ฉันได้เรียนรู้เกี่ยวกับสิ่งนี้จากคำตอบของ davor เกี่ยวกับการแสดงเอาต์พุตพรอมต์คำสั่งของ Windows และเปลี่ยนเส้นทางไปยังไฟล์ซึ่งคุณจะพบการอ้างอิงถึงยูทิลิตี้ unix ด้วย
โซลูชันที่จัดทำโดย "Tomas R" ทำงานได้อย่างสมบูรณ์แบบสำหรับคำถามของ OP และสามารถใช้ได้โดยกำเนิด
ลอง: chkdsk c:> output.txt | พิมพ์ output.txt
ผลลัพธ์เป็นของคำสั่งนี้เกี่ยวข้องกับเปอร์เซ็นต์ความสมบูรณ์ที่ได้รับเอาต์พุตแบบต่อเนื่องไปยังไฟล์ดังนั้นมันจะดูยุ่งเล็กน้อย (กล่าวคือข้อความจะถูกต่อท้ายเมื่อดำเนินการ) สิ่งนี้ไม่เกิดขึ้นกับบิตที่ได้รับเอาต์พุตไปยัง STDOUT (หน้าจอ) มันจะเป็นอย่างไรถ้าคุณทำคำสั่งเดิมโดยไม่เปลี่ยนเส้นทาง
ฉันคิดว่าคุณต้องการบางอย่างตามแนวนี้:
echo Your Msg> YourTxtFile.txt
หรือหากต้องการขึ้นบรรทัดใหม่:
echo Your Msg>> YourTxtFile.txt
คำสั่งเหล่านี้เหมาะสำหรับบันทึก
หมายเหตุ: บางครั้งอาจเกิดความผิดพลาดและแทนที่ไฟล์ข้อความทั้งหมดในคอมพิวเตอร์ของฉัน
หมายเหตุอื่น: หากไม่มีไฟล์อยู่ไฟล์จะสร้างไฟล์
>
ถูกออกแบบมาเพื่อแทนที่การใช้ไฟล์. >>
เพื่อผนวก )