หมายเหตุ:
* คำตอบนี้อาจลึกกว่ากรณีใช้งานหมายจับและfind 2>/dev/null
อาจดีพอในหลาย ๆ สถานการณ์ มันอาจยังเป็นที่สนใจสำหรับมุมมองข้ามแพลตฟอร์มและสำหรับการอภิปรายเกี่ยวกับเทคนิคเชลล์ขั้นสูงบางอย่างในความสนใจในการค้นหาวิธีแก้ปัญหาที่แข็งแกร่งที่สุดเท่าที่จะเป็นไปได้แม้ว่าคดีที่ได้รับการปกป้องอาจเป็นสมมุติฐาน
* หากระบบของคุณได้รับการกำหนดค่าให้แสดงข้อความแสดงข้อผิดพลาดที่แปลแล้วให้นำหน้าการfind
โทรด้านล่างด้วยLC_ALL=C
( LC_ALL=C find ...
) เพื่อให้แน่ใจว่ามีการรายงานข้อความภาษาอังกฤษเพื่อให้grep -v 'Permission denied'
ทำงานได้ตามที่ต้องการ คงเส้นคงวา แต่ข้อผิดพลาดใด ๆ ที่ไม่ได้แสดงแล้วจะเป็นภาษาอังกฤษได้เป็นอย่างดี
หากคุณเปลือกbash
หรือzsh
มีวิธีการแก้ปัญหาที่มีประสิทธิภาพในขณะที่ความเรียบง่ายที่สมเหตุสมผลโดยใช้เพียง POSIX สอดคล้องกับfind
คุณลักษณะ ; ในขณะที่bash
ตัวมันเองไม่ได้เป็นส่วนหนึ่งของ POSIX แต่แพลตฟอร์ม Unix ที่ทันสมัยส่วนใหญ่จะมาพร้อมกับมันทำให้โซลูชันนี้สามารถพกพาได้อย่างกว้างขวาง:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
หมายเหตุ: มีโอกาสเล็กน้อยที่grep
เอาต์พุตบางรายการอาจมาถึงหลังจาก find
เสร็จสิ้นเนื่องจากคำสั่งโดยรวมไม่รอให้คำสั่งภายใน>(...)
เสร็จสิ้น ในbash
คุณสามารถป้องกันสิ่งนี้ได้โดยต่อท้าย| cat
คำสั่ง
>(...)
เป็น (ไม่ค่อยได้ใช้) การส่งออก ทดแทนกระบวนการที่ช่วยให้การเปลี่ยนเส้นทางออก (ในกรณีนี้, stderrเอาท์พุท ( 2>
) เพื่อ stdin ภายในคำสั่ง>(...)
.
นอกจากbash
และzsh
, ksh
การสนับสนุนพวกเขาเช่นกันในหลักการแต่พยายามที่จะรวมกับการเปลี่ยนเส้นทางจากstderrเช่นเดียวกับที่นี่ ( 2> >(...)
) ดูเหมือนว่าจะถูกละเว้นใน (เงียบksh 93u+
)
grep -v 'Permission denied'
กรองออก ( -v
) ทุกบรรทัด (จากfind
กระแส stderr คำสั่ง) ที่มีวลีPermission denied
และผลเส้นที่เหลือให้ stderr ( >&2
)
วิธีนี้คือ:
ที่มีประสิทธิภาพ : grep
จะใช้กับข้อความแสดงข้อผิดพลาดเท่านั้น(และไม่ใช่การรวมกันของพา ธ ไฟล์และข้อความแสดงข้อผิดพลาดซึ่งอาจนำไปสู่ผลบวกปลอม) และข้อความแสดงข้อผิดพลาดอื่น ๆ
ผลข้างเคียงฟรี : find
รหัสออกของจะถูกเก็บรักษาไว้: การไม่สามารถเข้าถึงรายการระบบไฟล์อย่างน้อยหนึ่งรายการที่พบผลลัพธ์ในรหัสออก1
(แม้ว่าจะไม่บอกคุณว่ามีข้อผิดพลาดอื่น ๆนอกเหนือจากรายการที่ถูกปฏิเสธการอนุญาตเกิดขึ้นหรือไม่)
โซลูชันที่สอดคล้องกับ POSIX:
โซลูชันที่สอดคล้องกับ POSIX อย่างสมบูรณ์อาจมีข้อ จำกัด หรือต้องการงานเพิ่มเติม
หากfind
เอาต์พุตของจะถูกจับในไฟล์อย่างไรก็ตาม (หรือถูกระงับทั้งหมด) ดังนั้นโซลูชันที่อิงกับไพพ์ไลน์จากคำตอบของ Jonathan Lefflerนั้นเรียบง่ายแข็งแกร่งและสอดคล้องกับ POSIX:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
โปรดทราบว่าคำสั่งของเรื่องเปลี่ยนเส้นทางนี้2>&1
จะต้องมาเป็นครั้งแรก
จับเอาท์พุท stdout ในไฟล์ขึ้นด้านหน้าช่วยให้2>&1
การส่งเฉพาะข้อความผิดพลาดที่ผ่านท่อซึ่งgrep
สามารถแล้วไม่น่าสงสัยเกี่ยวกับการใช้งาน
เพียงข้อเสียคือว่ารหัสทางออกโดยรวมจะเป็นgrep
คำสั่งที่ไม่find
's ซึ่งในกรณีนี้หมายถึง: ถ้ามีไม่มีข้อผิดพลาดเลยหรือเพียงข้อผิดพลาดได้รับอนุญาตปฏิเสธรหัสทางออกจะได้รับ1
(การส่งสัญญาณความล้มเหลว ) มิฉะนั้น ( ข้อผิดพลาดอื่นที่ไม่ใช่การปฏิเสธสิทธิ์) 0
- ซึ่งตรงกันข้ามกับเจตนา
ที่กล่าวว่าfind
รหัสทางออกของไม่ค่อยใช้บ่อยเพราะมันมักจะสื่อข้อมูลเล็ก ๆ น้อย ๆ เกินความล้มเหลวขั้นพื้นฐานเช่นผ่านเส้นทางที่ไม่มีอยู่
อย่างไรก็ตามกรณีเฉพาะของบางคนเท่านั้นเส้นทางการป้อนข้อมูลที่เป็นไม่สามารถเข้าถึงได้เนื่องจากการขาดการสิทธิ์ที่จะสะท้อนให้เห็นในfind
's รหัสออก (ทั้งในและ GNU BSD find
): ถ้าข้อผิดพลาดสิทธิ์ปฏิเสธเกิดขึ้นใด ๆ1
ของไฟล์ที่ประมวลผลรหัสทางออกที่ถูกกำหนดเป็น
รูปแบบที่อยู่ต่อไปนี้ที่:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
ตอนนี้โค้ดทางออกบ่งชี้ว่ามีข้อผิดพลาดอื่น ๆ นอกเหนือจากที่ Permission denied
เกิดขึ้นหรือไม่: 1
ถ้าเป็นเช่น0
นั้น
กล่าวอีกนัยหนึ่ง: รหัสออกตอนนี้สะท้อนให้เห็นถึงเจตนาที่แท้จริงของคำสั่ง: success ( 0
) ถูกรายงานหากไม่มีข้อผิดพลาดเกิดขึ้นทั้งหมดหรือเฉพาะข้อผิดพลาดที่ได้รับอนุญาตปฏิเสธเกิดขึ้น
นี่คือเนื้อหาที่ดียิ่งขึ้นกว่าเพียงแค่ส่งfind
รหัสออกผ่านเหมือนในโซลูชันที่ด้านบน
gniourf_gniourfในความคิดเห็นเสนอข้อตกลงทั่วไป (ตาม POSIX) ยังคงของการแก้ปัญหานี้โดยใช้การเปลี่ยนเส้นทางที่ซับซ้อนซึ่งทำงานแม้กับพฤติกรรมเริ่มต้นของการพิมพ์เส้นทางไฟล์ไปยังstdout :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
กล่าวโดยย่อ: ตัวอธิบายไฟล์ที่กำหนดเอง3
ถูกใช้เพื่อสลับ stdout ( 1
) และ stderr ( 2
) ชั่วคราวเพื่อให้สามารถส่งข้อความแสดงข้อผิดพลาดเพียงอย่างเดียวgrep
ผ่าน stdout ได้
โดยไม่ต้องเปลี่ยนเส้นทางเหล่านี้ทั้งข้อมูล (เส้นทางแฟ้ม) และข้อความผิดพลาดจะได้รับการประปาgrep
ผ่าน stdout และgrep
จากนั้นก็จะไม่สามารถที่จะแยกแยะความแตกต่างระหว่างข้อผิดพลาด Permission denied
และ (สมมุติ) ไฟล์ที่มีชื่อที่เกิดขึ้นจะมีPermission denied
คำพูดที่ว่า
เช่นเดียวกับในโซลูชันแรกรหัสทางออกที่รายงานจะเป็นgrep
'ไม่ใช่find
' แต่สามารถใช้วิธีแก้ไขแบบเดียวกับข้างต้นได้
หมายเหตุเกี่ยวกับคำตอบที่มีอยู่:
มีหลายจุดที่จะต้องทราบเกี่ยวกับคำตอบของไมเคิล Brux ของ , find . ! -readable -prune -o -print
:
มันต้องGNU find
; มันไม่ทำงานบน macOS แน่นอนว่าถ้าคุณต้องการคำสั่งให้ทำงานกับ GNU find
เท่านั้นสิ่งนี้จะไม่เป็นปัญหาสำหรับคุณ
Permission denied
ข้อผิดพลาดบางอย่างอาจยังคงปรากฏ: find ! -readable -prune
รายงานข้อผิดพลาดดังกล่าวสำหรับรายการลูกของไดเรกทอรีที่ผู้ใช้ปัจจุบันได้r
รับอนุญาต แต่ไม่มีx
สิทธิ์ (ปฏิบัติการ) เหตุผลก็คือว่าเพราะไดเรกทอรีของตัวเองเป็นที่อ่าน-prune
ไม่ได้ดำเนินการและความพยายามที่จะลงมาลงในไดเรกทอรีที่แล้วก่อให้เกิดข้อผิดพลาด ที่กล่าวว่ากรณีทั่วไปคือการr
อนุญาตจะหายไป
หมายเหตุ: ประเด็นต่อไปนี้เป็นเรื่องของปรัชญาและ / หรือกรณีการใช้งานที่เฉพาะเจาะจงและคุณอาจตัดสินใจว่ามันไม่เกี่ยวข้องกับคุณและคำสั่งนั้นเหมาะกับความต้องการของคุณเป็นอย่างดีโดยเฉพาะอย่างยิ่งถ้าเพียงแค่พิมพ์เส้นทางเท่านั้น
- หากคุณคิดว่าการกรองข้อความแสดงข้อผิดพลาดที่ได้รับอนุญาตนั้นเป็นงานแยกต่างหากที่คุณต้องการใช้กับคำสั่งใด ๆ
find
แนวทางที่ตรงกันข้ามของการป้องกันข้อผิดพลาดที่ถูกปฏิเสธในเชิงรุกต้องมีการนำเสนอ "สัญญาณรบกวน" ลงในfind
คำสั่ง ความซับซ้อนและตรรกะข้อผิดพลาด
- ยกตัวอย่างเช่นตัวมากขึ้นได้รับการโหวตความคิดเห็นเกี่ยวกับคำตอบของไมเคิล (เช่นการเขียนนี้) ความพยายามที่จะแสดงให้เห็นว่าการขยายคำสั่งโดยรวมถึงการ
-name
กรองดังนี้
find . ! -readable -prune -o -name '*.txt'
นี้ แต่ไม่ได้ทำงานตามที่ตั้งใจไว้เพราะต่อท้าย-print
การดำเนินการที่จำเป็น (คำอธิบายสามารถพบได้ในคำตอบนี้ ) รายละเอียดปลีกย่อยดังกล่าวสามารถแนะนำข้อบกพร่อง
วิธีการแก้ปัญหาครั้งแรกในคำตอบของโจนาธาน Leffler ของ , find . 2>/dev/null > files_and_folders
เป็นตัวเขาเองรัฐ สุ่มสี่สุ่มห้าเงียบทุกข้อความผิดพลาด (และวิธีแก้ปัญหาคือยุ่งยากและไม่แข็งแกร่งอย่างเต็มที่ในขณะที่เขายังอธิบาย) อย่างไรก็ตามในทางปฏิบัติการพูดเป็นวิธีแก้ปัญหาที่ง่ายที่สุดเนื่องจากคุณอาจมีเนื้อหาที่จะสันนิษฐานว่าข้อผิดพลาดใด ๆ และทั้งหมดจะเกี่ยวข้องกับการอนุญาต
คำตอบหมอกของ , sudo find . > files_and_folders
, กระชับและจริงจัง แต่ไม่รอบคอบสำหรับสิ่งอื่นมากกว่าแค่พิมพ์ชื่อไฟล์เพื่อความปลอดภัยเพราะคุณใช้เป็นรากของผู้ใช้ "คุณมีความเสี่ยงทั้งระบบของคุณจะถูก messed ขึ้นจากข้อผิดพลาดในการหา หรือเวอร์ชันที่เป็นอันตรายหรือการเรียกที่ไม่ถูกต้องซึ่งเขียนสิ่งที่ไม่คาดคิดซึ่งไม่สามารถเกิดขึ้นได้หากคุณใช้สิ่งนี้ด้วยสิทธิ์ปกติ "(จากความคิดเห็นเกี่ยวกับคำตอบของหมอกโดยtripleee )
วิธีการแก้ปัญหาครั้งที่ 2 ในคำตอบ viraptor ของ , find . 2>&1 | grep -v 'Permission denied' > some_file
จะเสี่ยงต่อการบวกเท็จ (เนื่องจากส่งส่วนผสมของ stdout และ stderr ผ่านท่อ) และอาจแทนการรายงานไม่ใช่ข้อผิดพลาด -permission ปฏิเสธผ่าน stderr จับพวกเขาควบคู่ไปกับเส้นทางการส่งออก ในไฟล์เอาต์พุต
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?