นำออก 'การเข้าถึงปฏิเสธ "เส้น


9

เมื่อฉันใช้findเพื่อดูไฟล์ทั้งหมดที่ไฟล์ PDF ในไดเรกทอรีที่ผมเห็น/home access deniedเพื่อกำจัดพวกเขาฉันพยายาม:

find /home -iname "*.pdf" | grep -v "access denied"

อย่างไรก็ตามผลลัพธ์เหมือนกัน ฉันจะกำจัดบรรทัดเหล่านี้ได้อย่างไร


คำตอบ:


19

สิ่งที่คุณพยายามที่ไม่ได้ทำงานเพราะaccess deniedการส่งออกมีข้อผิดพลาดและส่ง STDERR แทน STDOUT grepซึ่งเป็นประปา

คุณสามารถหลีกเลี่ยงการเห็นข้อผิดพลาดเหล่านั้นด้วยการเปลี่ยนเส้นทางเพียง STDERR

find /home -iname "*.pdf" 2>/dev/null

หรืออย่างที่David Foerster แสดงความคิดเห็นเราสามารถปิด STDERR ได้อย่างกระชับยิ่งขึ้น

find /home -iname "*.pdf" 2>&-

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

find ~ -iname "*.pdf"

หากข้อผิดพลาดอาจแสดงว่ามีเจ้าของที่ไม่ถูกต้องในการกำหนดค่าท้องถิ่นของคุณซึ่งคุณควรตรวจสอบ


3
Grrr ทำไมผู้คนถึงชนะฉันถึง 30 วินาที? : \
รับผิดชอบต่อการไม่ใช้สิทธิ์

ค้นหา:“ /home/ihsan/.gvfs”: การเข้าถึงถูกปฏิเสธ find:“ /home/ihsan/.dbus”: การเข้าถึงถูกปฏิเสธ, สำหรับคำสั่ง ~
solfish

มีอะไรผิดปกติหรือเปล่า? ใช่ฉันยังต้องการไดเรกทอรีบ้านของผู้ใช้รายอื่นซึ่งฉันสร้างขึ้นเพื่อทดสอบด้วย
solfish

2
@olfish เท่าที่ฉันรู้ว่าไฟล์เหล่านั้นควรจะเป็นของคุณ คุณอาจต้องการsudo chown $USER: ~/.gvfs ~/.dbus
Zanna

1
มันควรจะเพียงพอที่จะ stderr 2>&-ใกล้ชิดกับ GNU พบว่าจะไม่ยุติหากพยายามเขียนข้อความแสดงข้อผิดพลาดไปยังตัวบอกความผิดปกติของไฟล์ สำหรับปัญหาที่เป็นเจ้าของจะมีประสิทธิภาพมากขึ้นในกรณีของไฟล์ภายในที่ไม่ได้เป็นเจ้าของsudo chown -R $USER: ... $USER
David Foerster

8

การเข้าถึงปฏิเสธอาจจะถูกพิมพ์ลงบนมากกว่าstderrstdout

ลองสิ่งนี้:

find /home -iname "*.pdf" 2>&1 | grep -v "access denied"

การ2>&1เปลี่ยนเส้นทางผลลัพธ์จากstderrไปยังstdoutเพื่อให้grep -vสามารถทำงานได้ (โดยค่าเริ่มต้น|จะมีเพียงท่อstdoutและไม่stderrเท่านั้น)


แต่สำหรับ 2> & 1 นี้หมายความว่าถ้า stderr มีอยู่ส่งไปยัง stdout หรือไม่
solfish

@solish Yup นั่นคือสิ่งที่แน่นอน :)
You'reAGitForNotUsingGit

สิ่งที่ฉันไม่เข้าใจมาก่อน "|" เป็นเอาท์พุท; เราได้ stderr ใช่มั้ย และหลัง "|" ในฐานะอินพุตเราได้รับสิ่งนี้
solfish

@ ความชั่วร้ายฉันพบปัญหานี้ประมาณหนึ่งปีครึ่งที่ผ่านมาและฉันสามารถแก้ไขได้โดยใช้วิธีอื่น แต่จากนั้นความคิดเห็นด้านล่างคำตอบของฉันแนะนำให้ใช้เพียงแค่2>&1... ฉันไม่ใช่ผู้เชี่ยวชาญทุบตีดังนั้นถ้าไม่ถูกต้องแล้วโปรดพูดอย่างนั้น :)
You'reAGitForNotUsingGit

@AndroidDev ฉันขอแนะนำให้เพิ่มวิธีการที่แตกต่างกันในคำตอบนี้เป็นทางเลือก คำติชมของ Etan Reisnerคือการแทนที่กระบวนการไม่สามารถพกพาได้ แต่bashในอูบุนตูมียกเว้นในโหมด POSIX ฉันคิดว่านี่เป็นทางออกที่ดีที่สุด - ไฟล์ที่มีชื่อประสงค์ร้ายaccess deniedจะยังคงปรากฏ
Eliah Kagan

4

คุณอาจหมายถึง "การอนุญาตที่ถูกปฏิเสธ" ซึ่งเป็นสิ่งที่findในอูบุนตูแสดงให้คุณเห็นเมื่อคุณไม่สามารถเข้าถึงบางสิ่งได้เนื่องจากสิทธิ์ของไฟล์ - แทนที่จะเป็น "การเข้าถึงถูกปฏิเสธ"

คำสั่งทั่วไปอย่างครบถ้วนหนึ่งคำสั่งที่ทำอย่างถูกต้อง (และเป็นโบนัสสามารถพกพาไปยัง*อื่น ๆ ได้ตราบใดที่ข้อความแสดงข้อผิดพลาดเหมือนกัน) คือ:

(find 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-

(โดยปกติคุณต้องการส่งอาร์กิวเมนต์บางอย่างไปที่findสิ่งเหล่านั้นไปก่อนการเปลี่ยนเส้นทางครั้งแรก3>&1)

อย่างไรก็ตามบ่อยครั้งที่คุณจะสามารถใช้สิ่งที่ง่ายกว่า ตัวอย่างเช่นคุณอาจจะสามารถใช้ทดแทนกระบวนการ รายละเอียดดังนี้

วิธีการที่พบบ่อยที่สุดและข้อ จำกัด ของพวกเขา

วิธีทั่วไปสองวิธีคือการทิ้งstderr (ตามคำตอบของ Zanna ) หรือเปลี่ยนเส้นทาง stderr ไปยังstdoutและกรอง stdout (เช่นเดียวกับในคำตอบของ Android Dev ) แม้ว่าพวกเขาจะมีข้อได้เปรียบในการเขียนง่าย ๆ และมักเป็นทางเลือกที่สมเหตุสมผล แต่วิธีการเหล่านี้ไม่เหมาะ

การละทิ้งทุกสิ่งที่ส่งไปยัง stderrเช่นโดยการเปลี่ยนเส้นทางไปยังอุปกรณ์ nullด้วย2>/dev/nullหรือโดยปิดด้วย2>&-- ทำให้มีความเสี่ยงที่จะเกิดข้อผิดพลาดที่ขาดหายไปนอกจาก "ปฏิเสธสิทธิ์"

"การอนุญาตที่ถูกปฏิเสธ" อาจเป็นข้อผิดพลาดที่พบบ่อยที่สุดเมื่อเรียกใช้findแต่มันอยู่ไกลจากข้อผิดพลาดที่เป็นไปได้เท่านั้นและหากมีข้อผิดพลาดเกิดขึ้นอีกคุณอาจต้องการทราบเกี่ยวกับมัน โดยเฉพาะอย่างยิ่งfindรายงาน "ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" หากไม่มีจุดเริ่มต้น ด้วยจุดเริ่มต้นหลายจุดfindอาจยังคงให้ผลลัพธ์ที่มีประโยชน์และปรากฏว่าใช้งานได้ ตัวอย่างเช่นถ้าaและcอยู่ แต่bไม่ได้find a b c -name xพิมพ์ผลในaแล้ว "ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" สำหรับแล้วผลในการbc

การรวม stdout และ stderr เข้าด้วยกันเป็น stdout และไพพ์ไปยังgrepหรือคำสั่งอื่น ๆ เพื่อกรอง - เช่นเดียวกับ2>&1 | grep ...หรือ|& grep ...- เสี่ยงต่อการกรองไฟล์โดยไม่ได้ตั้งใจซึ่งชื่อนั้นมีข้อความที่ถูกกรอง

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

การกรองสตรีมแบบรวมมีปัญหาอื่นซึ่งไม่สามารถบรรเทาได้ด้วยการกรองแบบเลือกใช้มากขึ้น (เช่นด้วยgrep -vx 'find: .*: Permission denied'ที่ด้านขวาของไพพ์) findการดำเนินการบางอย่างรวมถึงการ-printกระทำที่เป็นนัยเมื่อคุณระบุไม่มีการดำเนินการกำหนดวิธีการส่งออกชื่อไฟล์โดยพิจารณาว่าstdoutเป็นเทอร์มินัลหรือไม่

  • หากไม่ใช่เทอร์มินัลชื่อไฟล์จะถูกส่งออกตาม - แม้ว่าจะมีอักขระแปลก ๆ เช่นบรรทัดใหม่และอักขระควบคุมที่สามารถเปลี่ยนลักษณะการทำงานของเทอร์มินัลของคุณ หากเป็นเทอร์มินัลอักขระเหล่านี้จะถูกระงับและ?ถูกพิมพ์แทน
  • นี่คือสิ่งที่คุณต้องการ หากคุณกำลังจะประมวลผลชื่อไฟล์ต่อไปพวกเขาจะต้องส่งออกอย่างแท้จริง อย่างไรก็ตามหากคุณกำลังจะแสดงชื่อไฟล์ที่ขึ้นบรรทัดใหม่อาจเลียนแบบชื่อไฟล์หลายชื่อและชื่อไฟล์ที่มีลำดับของอักขระ backspace อาจปรากฏเป็นชื่ออื่น นอกจากนี้ยังอาจมีปัญหาอื่น ๆ เช่นชื่อไฟล์ที่มีลำดับการหลีกเลี่ยงที่เปลี่ยนสีในเทอร์มินัลของคุณ
  • แต่การไพพ์ผลลัพธ์การค้นหาผ่านคำสั่งอื่น (เช่นgrep) ทำให้findไม่เห็นเทอร์มินัลอีกต่อไป (แม่นยำยิ่งขึ้นทำให้ stdout ไม่ใช่เทอร์มินัล) จากนั้นอักขระแปลก ๆ จะถูกส่งออกอย่างแท้จริง แต่ถ้าคำสั่งทั้งหมดทางด้านขวาของไปป์นั้นคือ(a)ลบบรรทัดที่ดูเหมือนข้อความ "สิทธิ์ที่ถูกปฏิเสธ" และ(b)พิมพ์สิ่งที่เหลืออยู่คุณจะยังคงอยู่ภายใต้ประเภทของ shenanigans ที่findเทอร์มินัล การตรวจจับมีวัตถุประสงค์เพื่อป้องกัน
  • ดูส่วนไฟล์ที่ผิดปกติของman findสำหรับข้อมูลเพิ่มเติมรวมถึงพฤติกรรมของแต่ละการกระทำที่พิมพ์ชื่อไฟล์ ( "หลายการกระทำของผลการค้นหาในการพิมพ์ของข้อมูลซึ่งอยู่ภายใต้การควบคุมของผู้ใช้อื่น ๆ ..." ) ดูเพิ่มเติมส่วน3.3.2.1 , 3.3.2.2และ3.3.2.3ของคู่มืออ้างอิง GNU Findutils

การสนทนาข้างต้นของชื่อไฟล์ผิดปกติที่เกี่ยวข้องกับGNU findซึ่งเป็นการfindใช้งานในระบบ GNU / Linux รวมถึง Ubuntu

ออกจากเอาต์พุตมาตรฐานเพียงอย่างเดียวขณะกรองข้อผิดพลาดมาตรฐาน

สิ่งที่คุณจริงๆต้องการที่นี่คือการปล่อยstdoutเหมือนเดิมในขณะที่ท่อstderrgrepไป น่าเสียดายที่ไม่มีเรื่องง่ายสำหรับเรื่องนี้ |pipes stdout และเชลล์บางตัว (รวมถึงbash) รองรับ|&ไพพ์ทั้งสองสตรีมหรือคุณสามารถเปลี่ยนเส้นทาง stderr ไปยัง stdout ก่อนด้วย2>&1 |ซึ่งมีผลเหมือนกัน แต่เชลล์ที่ใช้กันทั่วไปไม่ได้มีไวยากรณ์ให้กับไปป์ stderr เท่านั้น

คุณยังสามารถทำสิ่งนี้ได้ มันน่าอึดอัดใจ วิธีหนึ่งคือการสลับ stdout กับ stderrเพื่อให้ผลการค้นหาอยู่ใน stderr และข้อผิดพลาดอยู่ใน stdout จากนั้นไปที่ stdout ไปที่grepเพื่อกรอง:

find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'

โดยปกติคุณจะส่งผ่านข้อโต้แย้งไปยังfindเช่นจุดเริ่มต้น (สถานที่ที่จะค้นหาซึ่งมักจะเป็นไดเรกทอรี) และภาคแสดง (การทดสอบและการกระทำ) การเดินทางเหล่านี้ในสถานที่ของargsดังกล่าวข้างต้น

สิ่งนี้ทำงานได้โดยการแนะนำfile descriptorใหม่เพื่อเก็บหนึ่งในสองสตรีมมาตรฐานที่คุณต้องการสลับ, ทำการเปลี่ยนเส้นทางเพื่อสลับพวกเขาและปิดตัวบ่งชี้ไฟล์ใหม่

  • ตัวอธิบายไฟล์ 1 คือ stdout และ 2 คือ stderr (และ 0 ที่ไม่ได้บอกทางคือstdin ) แต่คุณยังสามารถเปลี่ยนเส้นทางโดยใช้ตัวอธิบายไฟล์อื่น ๆ สามารถใช้เพื่อเปิดหรือเปิดไฟล์หรืออุปกรณ์ต่อไปได้
  • 3>&1 เปลี่ยนเส้นทาง file descriptor 3 ไปที่ stdout ดังนั้นเมื่อ stdout (file descriptor 1) ถูกเปลี่ยนเส้นทางในภายหลัง stdout ดั้งเดิมยังคงสามารถเขียนได้อย่างง่ายดาย
  • 1>&2เปลี่ยนเส้นทาง stdout ไปยัง stderr เนื่องจาก file descriptor 3 ยังคงเป็น stdout ดั้งเดิมจึงยังสามารถเข้าถึงได้
  • 2>&3 เปลี่ยนเส้นทาง stderr ไปยัง file descriptor 3 ซึ่งเป็น stdout ดั้งเดิม
  • 3>&- ปิดไฟล์ descriptor 3 ซึ่งไม่จำเป็นอีกต่อไป
  • สำหรับข้อมูลเพิ่มเติมโปรดดูที่วิธีไปป์ stderr และไม่ใช่ stdout และIO Redirection - การสลับ stdout และ stderr (ขั้นสูง)และโดยเฉพาะไปป์ stderr ผ่านตัวกรองเท่านั้น

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

วิธีแก้ปัญหาคือการสลับสตรีมกลับหลังจากกรองเอาท์พุทเสร็จแล้ว การใช้การเปลี่ยนเส้นทางแบบเดียวกันที่แสดงด้านบนทางด้านขวาของไปป์ไลน์จะไม่บรรลุเป้าหมายนี้เพราะ|ไปป์ stdout เท่านั้นดังนั้นด้านข้างของไปป์ไลน์จะรับเอาท์พุทที่ส่งไปยัง stderr เท่านั้น (เพราะกระแสถูกเปลี่ยน) และไม่ใช่ต้นฉบับ เอาต์พุต stdout แต่คุณสามารถใช้( )เพื่อเรียกใช้คำสั่งข้างต้นใน subshell ( ที่เกี่ยวข้อง ) จากนั้นใช้การเปลี่ยนเส้นทางการแลกเปลี่ยนกับที่:

(find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-

มันคือการจัดกลุ่มไม่ใช่เฉพาะ subshell ซึ่งทำให้งานนี้ หากคุณต้องการคุณสามารถใช้{ ;}:

{ find args 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'; } 3>&1 1>&2 2>&3 3>&-

วิธีที่ยุ่งยากน้อยกว่า: การทดแทนกระบวนการ

เชลล์บางตัวรวมถึง Bash ในระบบที่สามารถรองรับได้ (รวมถึงระบบ GNU / Linux เช่น Ubuntu) ให้คุณทำการทดแทนกระบวนการซึ่งช่วยให้คุณสามารถรันคำสั่งและเปลี่ยนเส้นทางไปยัง / จากสตรีมของหนึ่งในนั้น คุณสามารถเปลี่ยนเส้นทางfindคำสั่ง stderr ไปยังgrepคำสั่งที่กรองและเปลี่ยนเส้นทางgrepstdout ของคำสั่งนั้นไปยัง stderr

find args 2> >(grep -Fv 'Permission denied' >&2)

เครดิตไปที่Android Devสำหรับแนวคิดนี้

แม้ว่าจะbash รองรับการทดแทนกระบวนการ แต่shใน Ubuntuก็dashไม่เป็นเช่นนั้น มันจะให้ "ข้อผิดพลาดทางไวยากรณ์: การเปลี่ยนเส้นทางที่ไม่คาดคิด" หากคุณพยายามใช้วิธีนี้ในขณะที่วิธีการเปลี่ยน stdout และ stderr จะยังคงใช้งานได้ นอกจากนี้เมื่อbashทำงานในโหมด POSIXการสนับสนุนการทดแทนกระบวนการจะถูกปิด

หนึ่งในสถานการณ์ที่bashวิ่งในโหมด POSIX คือเมื่อมันถูกเรียกว่าเป็น1sh ดังนั้นบนระบบปฏิบัติการเช่น Fedora ที่bashให้บริการ/bin/shหรือถ้าคุณสร้าง/bin/shจุดเชื่อมโยงให้กับbashตัวเองบน Ubuntu การทดแทนกระบวนการยังไม่สามารถใช้งานได้ในshสคริปต์โดยไม่ต้องใช้คำสั่งก่อนหน้าเพื่อปิดโหมด POSIX ทางออกที่ดีที่สุดของคุณหากคุณต้องการใช้วิธีนี้ในสคริปต์คือการใส่#!/bin/bash ที่ด้านบนแทน#!/bin/shถ้าคุณยังไม่ได้

1 : ในสถานการณ์นี้bashเปิดโหมด POSIX โดยอัตโนมัติหลังจากที่รันคำสั่งในสคริปต์เริ่มต้น

ตัวอย่าง

การทดสอบคำสั่งเหล่านี้มีประโยชน์ การทำเช่นนี้ฉันจะสร้างtmpไดเรกทอรีย่อยของไดเรกทอรีปัจจุบันและเติมมันมีบางไฟล์และไดเรกทอรีสละสิทธิ์ห่างจากหนึ่งของพวกเขาที่จะเรียก "ไม่อนุญาต" findข้อผิดพลาดใน

mkdir tmp; cd tmp; mkdir a b c; touch w a/x 'a/Permission denied messages.txt' b/y c/z; chmod 0 b

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

ek@Io:~/tmp$ find
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b
find: ‘./b’: Permission denied

การไปป์grepไลน์ทั้ง stdout และ stderr ไปยังและการกรองบรรทัดที่มี "สิทธิ์ที่ถูกปฏิเสธ" ทำให้ข้อความแสดงข้อผิดพลาดหายไป แต่ยังซ่อนผลลัพธ์การค้นหาไฟล์ที่มีวลีนั้นในชื่อ:

ek@Io:~/tmp$ find |& grep -Fv 'Permission denied'
.
./a
./a/x
./c
./c/z
./w
./b

find 2>&1 | grep -Fv 'Permission denied' เทียบเท่าและสร้างผลลัพธ์เดียวกัน

วิธีการที่แสดงด้านบนสำหรับการกรอง "ปฏิเสธสิทธิ์" จากข้อความแสดงข้อผิดพลาดเท่านั้นและไม่ได้มาจากผลการค้นหา - จะทำได้สำเร็จ ตัวอย่างเช่นต่อไปนี้เป็นวิธีการสลับ stdout และ stderr:

ek@Io:~/tmp$ (find 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b

find args 2> >(grep -Fv 'Permission denied' >&2) สร้างเอาต์พุตเดียวกัน

คุณสามารถทริกเกอร์ข้อความแสดงข้อผิดพลาดที่แตกต่างกันเพื่อให้แน่ใจว่าบรรทัดที่ส่งไปยัง stderr ที่ไม่มีข้อความ "ปฏิเสธการอนุญาต" ยังคงได้รับอนุญาตผ่าน ตัวอย่างเช่นที่นี่ฉันได้ทำงานfindกับไดเรกทอรีปัจจุบัน ( .) เป็นจุดเริ่มต้นหนึ่ง แต่ไดเรกทอรีไม่มีอยู่fooอีก:

ek@Io:~/tmp$ (find . foo 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
.
./a
./a/Permission denied messages.txt
./a/x
./c
./c/z
./w
./b
find: foo’: No such file or directory

การตรวจสอบfindเอาต์พุตมาตรฐานนั้นยังคงเป็นเทอร์มินัล

นอกจากนี้เรายังสามารถดูว่าคำสั่งใดทำให้อักขระพิเศษเช่นขึ้นบรรทัดใหม่ปรากฏขึ้นอย่างแท้จริง (สามารถทำได้แยกต่างหากจากการสาธิตด้านบนและไม่จำเป็นต้องอยู่ในtmpไดเรกทอรี)

สร้างไฟล์ด้วยบรรทัดใหม่ในชื่อ:

touch $'abc\ndef'

โดยปกติเราจะใช้ไดเรกทอรีเป็นจุดเริ่มต้นfindแต่ไฟล์ทำงานด้วย:

$ find abc*
abc?def

ท่อ stdout คำสั่งอื่นทำให้เกิดการขึ้นบรรทัดใหม่ที่จะออกมาอย่างแท้จริงในการสร้างความประทับใจที่ผิดพลาดของผลการค้นหาสองแยกและabc defเราสามารถทดสอบด้วยcat:

$ find abc* | cat
abc
def

การเปลี่ยนเส้นทาง just stderr ไม่ได้ทำให้เกิดปัญหานี้:

$ find abc* 2>/dev/null
abc?def

และไม่ปิดมัน:

$ find abc* 2>&-
abc?def

การไปป์ที่grep จะทำให้เกิดปัญหา:

$ find abc* |& grep -Fv 'Permission denied'
abc
def

(การแทนที่|&ด้วย2>&1 |ค่าเทียบเท่าและสร้างเอาต์พุตเดียวกัน)

การสลับ stdout และ stderr และ piping stdout ไม่ทำให้เกิดปัญหาfindstdout ของกลายเป็น stderr ซึ่งไม่ได้ถูกpiped:

$ find abc* 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied'
abc?def

การจัดกลุ่มคำสั่งนั้นและการสลับกระแสกลับไม่ทำให้เกิดปัญหา:

$ (find abc* 3>&1 1>&2 2>&3 3>&- | grep -Fv 'Permission denied') 3>&1 1>&2 2>&3 3>&-
abc?def

( { ;}เวอร์ชันสร้างเอาต์พุตเดียวกัน)

การใช้การทดแทนกระบวนการเพื่อกรอง stderr ไม่ทำให้เกิดปัญหาเช่นกัน:

$ find abc* 2> >(grep -Fv 'Permission denied' >&2)
abc?def
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.