เปลี่ยนเส้นทาง Windows cmd stdout และ stderr เป็นไฟล์เดียว


688

ฉันพยายามเปลี่ยนเส้นทางเอาต์พุตทั้งหมด (stdout + stderr) ของคำสั่งDOSเป็นไฟล์เดียว:

C:\>dir 1> a.txt 2> a.txt
The process cannot access the file because it is being used by another process.

เป็นไปได้หรือฉันควรเปลี่ยนเส้นทางไปยังสองไฟล์แยกกัน


14
TechNet: การใช้ตัวดำเนินการเปลี่ยนเส้นทางคำสั่ง (ตอบคำถามนี้ดีกว่าคำตอบใด ๆ ที่นี่)
Martin Prikryl

1
2> & 1 เนื่องจากไม่สามารถเปิดไฟล์เดียวกันได้อีกครั้ง
Luke

คำตอบ:


1090

คุณต้องการ:

dir > a.txt 2>&1

ไวยากรณ์2>&1จะเปลี่ยนเส้นทาง2(stderr) ไปยัง1(stdout) นอกจากนี้คุณยังสามารถซ่อนข้อความโดยการเปลี่ยนเส้นทางไปNUL, คำอธิบายเพิ่มเติมและตัวอย่างใน MSDN


32
ขอบคุณสำหรับสิ่งนี้ไม่ทราบว่าไวยากรณ์ของยูนิกซ์เชลล์นี้ทำงานสำหรับ DOS ด้วย!
chaindriver

20
มันดีมากสำหรับการซ่อนเอาท์พุททั้งหมด .. net stop w3svc >NUL 2>&1.. ขอบคุณ!
wasatchwizard

3
@wasatchwizard Ithink ฉันมีปัญหากับเรื่องนั้น แต่> NUL 2> NUL ทำงานได้ดี
FrinkTheBrave

13
หากมีจุดจับจะไม่มีช่องว่างระหว่างจุดจับ (เช่น 2) และตัวดำเนินการเปลี่ยนเส้นทาง (เช่น>) ดังนั้น2> 2.txtงาน (หรือ2> &1) 2 > 2.txtไม่; 2 > &1ไม่.
ถั่วแดง

9
ฉันรักมาก "อืมปัญหาแบบครั้งเดียวนี้จะใช้เวลาหนึ่งชั่วโมง" ฉันใช้เวลานานในการพิมพ์ความคิดเห็นนี้มากกว่าที่จะหาคำตอบนี้
แบรนดอน

195

คำตอบของ Anders Lindahl นั้นถูกต้อง แต่ควรสังเกตว่าหากคุณเปลี่ยนเส้นทาง stdout ไปยังไฟล์และต้องการเปลี่ยนเส้นทาง stderr ด้วยเช่นกันคุณต้องแน่ใจว่า2>&1ได้ระบุไว้หลังการ1>เปลี่ยนเส้นทางมิฉะนั้นจะไม่ทำงาน

REM *** WARNING: THIS WILL NOT REDIRECT STDERR TO STDOUT ****
dir 2>&1 > a.txt

10
หลังจากสิ่งที่มีค่าใช้จ่ายฉันชั่วโมงเพื่อค้นหาสิ่งที่ผิด DelboyJay! ขอบคุณ!
Nam G VU

4
มันอธิบายได้ทุกที่ทำไมการวาง 2> & 1 ก่อน 1> จะไม่บรรลุผลตามที่ตั้งใจไว้? ฉันสงสัยอย่างยิ่งว่าสิ่งนี้เกี่ยวข้องกับคำสั่ง "cmd" วิเคราะห์คำที่ให้ความหมายที่แตกต่างกันสองประการขึ้นอยู่กับลำดับที่คุณระบุการเปลี่ยนเส้นทาง แต่กฎความหมายถูกบันทึกไว้ที่ใดก็ได้เพราะฉันคิดว่านี่เป็นสิ่งที่คุ้มค่าที่จะเรียนรู้เพราะอาจเสียเวลาหลายชั่วโมง
igbgotiz

12
@igbgotiz 2> & 1 หมายถึง 'เปลี่ยนเส้นทางสตรีม 2 เป็นสตรีม 1' ดังนั้นคุณต้องตั้งค่าสตรีม 1 ก่อน
FrinkTheBrave

3
@FrinkTheBrave แต่สตรีม 1 เป็นเอาต์พุตมาตรฐาน (เช่นคอนโซล) หากไม่ได้ระบุไว้อย่างชัดเจน ที่ยังไม่ได้อธิบายมัน imho
MarioDS

1
@MDeSchaepmeester หากคุณdir 2>&1 > a.txtเป็นคนแรกคุณจะเปลี่ยนเส้นทาง ( >) สตรีม 2 (stderr) เพื่อสตรีม 1 (stdout) จากนั้นหลังจากที่ทั้งคู่เข้าร่วมกันแล้วคุณจะเปลี่ยนเส้นทาง stdout ( >โดยไม่มีตัวระบุ) ไปยังไฟล์ หากคุณต้องการให้ stderr ไปที่อื่นคุณจะไม่สามารถเข้าร่วมกับ stdout ก่อนได้
cp.engr

80

ข้อมูลความเป็นมาจาก MSKB

ในขณะที่คำตอบที่ได้รับการยอมรับสำหรับคำถามนี้ถูกต้อง แต่ก็ไม่ได้อธิบายอะไรมากนักว่าทำไมมันถึงทำงานได้จริงและเนื่องจากไวยากรณ์ไม่ชัดเจนในทันทีฉันจึงทำ google แบบด่วนเพื่อค้นหาว่าเกิดอะไรขึ้นจริง ด้วยความหวังว่าข้อมูลนี้จะเป็นประโยชน์ต่อผู้อื่นฉันโพสต์ไว้ที่นี่

ที่นำมาจากMS สนับสนุน KB 110930


จาก MSKB110930

การเปลี่ยนเส้นทางข้อความแสดงข้อผิดพลาดจากพรอมต์คำสั่ง: STDERR / STDOUT

สรุป

เมื่อเปลี่ยนเส้นทางเอาต์พุตจากแอปพลิเคชันโดยใช้สัญลักษณ์ '>' ข้อความแสดงข้อผิดพลาดจะยังคงพิมพ์ไปที่หน้าจอ นี่เป็นเพราะข้อความข้อผิดพลาดมักจะถูกส่งไปยังกระแสข้อผิดพลาดมาตรฐานแทนกระแสออกมาตรฐาน

เอาต์พุตจากแอ็พพลิเคชันหรือคำสั่งคอนโซล (Command Prompt) มักถูกส่งไปยังสตรีมแยกกันสองรายการ เอาต์พุตปกติถูกส่งไปที่ Standard Out (STDOUT) และข้อความผิดพลาดจะถูกส่งไปที่ Standard Error (STDERR) เมื่อคุณเปลี่ยนเส้นทางคอนโซลเอาต์พุตโดยใช้สัญลักษณ์ ">" คุณจะเปลี่ยนเส้นทาง STDOUT เท่านั้น ในการเปลี่ยนเส้นทาง STDERR คุณต้องระบุ '2>' สำหรับสัญลักษณ์การเปลี่ยนเส้นทาง นี่เป็นการเลือกเอาต์พุตสตรีมที่สองซึ่งคือ STDERR

ตัวอย่าง

คำสั่งdir file.xxx(ที่file.xxxไม่มีอยู่) จะแสดงผลลัพธ์ต่อไปนี้:

Volume in drive F is Candy Cane Volume Serial Number is 34EC-0876

File Not Found

หากคุณเปลี่ยนเส้นทางผลลัพธ์ไปยังNULอุปกรณ์ที่ใช้dir file.xxx > nulคุณจะยังคงเห็นข้อความแสดงข้อผิดพลาดส่วนหนึ่งของผลลัพธ์เช่นนี้:

File Not Found

หากต้องการเปลี่ยนเส้นทาง (เฉพาะ) ข้อความแสดงข้อผิดพลาดไปยังให้NULใช้คำสั่งต่อไปนี้:

dir file.xxx 2> nul

หรือคุณสามารถเปลี่ยนเส้นทางผลลัพธ์ไปยังที่เดียวและข้อผิดพลาดไปที่อื่น

dir file.xxx > output.msg 2> output.err

คุณสามารถพิมพ์ข้อผิดพลาดและเอาต์พุตมาตรฐานไปยังไฟล์เดียวโดยใช้คำสั่ง "& 1" เพื่อเปลี่ยนทิศทางเอาต์พุตสำหรับ STDERR ไปยัง STDOUT แล้วส่งเอาต์พุตจาก STDOUT ไปยังไฟล์:

dir file.xxx 1> output.msg 2>&1

29

ในการเพิ่ม stdout และ stderr ให้กับล็อกไฟล์ทั่วไปของสคริปต์:

dir >> a.txt 2>&1

9
>>ผนวกไปยังไฟล์ที่>เขียนทับไฟล์
delliottg

13

ถูกต้องจัดการไฟล์ 1 สำหรับกระบวนการคือ STDOUT เปลี่ยนเส้นทางโดย1>หรือ>(1 สามารถละเว้นโดยการประชุมคำสั่งล่าม [cmd.exe] รู้ว่าจะจัดการกับมัน) จับไฟล์ที่ 2 คือ STDERR, 2>เปลี่ยนเส้นทาง

โปรดทราบว่าหากคุณกำลังใช้สิ่งเหล่านี้เพื่อสร้างไฟล์บันทึกนอกจากว่าคุณกำลังส่ง outut ไปที่ _uniquely_named_ (เช่นไฟล์บันทึกวันที่และเวลาประทับ) จากนั้นหากคุณเรียกใช้กระบวนการเดียวกันสองครั้งการเปลี่ยนเส้นทางจะเขียนทับ ( แทนที่) ไฟล์บันทึกก่อนหน้า

>>(อย่างใดอย่างหนึ่งหรือ STDOUT STDERR) จะผนวกไม่แทนที่ไฟล์ ดังนั้นคุณจะได้รับล็อกไฟล์สะสมแสดงผลจากการดำเนินการทั้งหมด - โดยทั่วไปมีประโยชน์มากกว่า

เส้นทางที่มีความสุข ...


2

อย่างไรก็ตามมีไม่รับประกันว่าผลลัพธ์ของSDTOUTและSTDERRมีการผสมผสานระหว่างบรรทัดโดยลำดับในเวลาที่เหมาะสมโดยใช้POSIXไวยากรณ์ผสานการเปลี่ยนเส้นทาง

หากแอปพลิเคชันใช้เอาต์พุตบัฟเฟอร์มันอาจเกิดขึ้นว่าข้อความของสตรีมหนึ่งถูกแทรกในอีกสตรีมที่ขอบเขตบัฟเฟอร์ซึ่งอาจปรากฏขึ้นตรงกลางของบรรทัดข้อความ

คนตัดไม้โดยเฉพาะคอนโซลเอาท์พุท (เช่น"StdOut/StdErr Logger"โดย'LoRd MuldeR') อาจจะมีความน่าเชื่อถือมากขึ้นสำหรับงานดังกล่าว

ดู: โครงการ OpenSource ของ MuldeR


0

ในแบตช์ไฟล์ (Windows 7 ขึ้นไป) ฉันพบว่าวิธีนี้น่าเชื่อถือที่สุด

Call :logging >"C:\Temp\NAME_Your_Log_File.txt" 2>&1
:logging
TITLE "Logging Commands"
ECHO "Read this output in your log file"
ECHO ..
Prompt $_
COLOR 0F

เห็นได้ชัดว่าใช้คำสั่งใดก็ได้ที่คุณต้องการและผลลัพธ์จะถูกนำไปยังไฟล์ข้อความ การใช้วิธีนี้มีความน่าเชื่อถืออย่างไรก็ตามไม่มีการแสดงผลบนหน้าจอ


(พื้นคำตอบเดียวที่ได้รับไม่กี่ครั้งปีที่ผ่านมา.) คุณสามารถบังคับให้ส่งออกไปยังหน้าจอที่มี>con echo This goes to screenยังมีประโยชน์สำหรับการป้อนข้อมูลของผู้ใช้>con set /p "var="Input: "หมายเหตุ: เส้นที่จะเพียงปรากฏบนหน้าจอและไม่ได้ถูกเปลี่ยนเส้นทางไปยังแฟ้ม
เตฟาน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.