หมายเหตุ:
* คำตอบนี้อาจลึกกว่ากรณีใช้งานหมายจับและ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?