วิธีการของ @ meuh ไม่มีประสิทธิภาพเนื่องจาก-maxdepth 1
วิธีการของเขายังช่วยให้find
อ่านเนื้อหาของไดเรกทอรีที่ระดับ 1 เพื่อเพิกเฉยต่อสิ่งเหล่านี้ในภายหลัง มันจะไม่ทำงานอย่างถูกต้องกับfind
การใช้งานบางอย่าง(รวมถึง GNU find
) ถ้าบางชื่อไดเรกทอรีมีลำดับของไบต์ที่ไม่ได้สร้างตัวละครที่ถูกต้องในสถานที่ของผู้ใช้ (เช่นชื่อไฟล์ในการเข้ารหัสอักขระที่แตกต่างกัน)
find . \( -name . -o -prune \) -extra-conditions-and-actions
เป็นวิธีที่ยอมรับได้มากขึ้นในการใช้ GNU -maxdepth 1
(หรือ FreeBSD's -depth -2
)
โดยทั่วไปแล้ว-depth 1
คุณต้องการ ( -mindepth 1 -maxdepth 1
) ตามที่คุณไม่ต้องการพิจารณา.
(ความลึก 0) จากนั้นง่ายยิ่งขึ้น:
find . ! -name . -prune -extra-conditions-and-actions
สำหรับ-maxdepth 2
ที่จะกลายเป็น:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
และนั่นคือสิ่งที่คุณทำงานในปัญหาของตัวละครที่ไม่ถูกต้อง
ตัวอย่างเช่นหากคุณมีไดเรกทอรีที่เรียกว่าStéphane
แต่é
มีการเข้ารหัสในชุดอักขระ iso8859-1 (aka latin1) (0xe9 ไบต์) ซึ่งพบได้ทั่วไปในยุโรปตะวันตกและอเมริกาจนถึงกลางปี 2000 ดังนั้น 0xe9 ไบต์จะไม่เป็น อักขระที่ถูกต้องใน UTF-8 ดังนั้นในโลแคล UTF-8 *
อักขระตัวแทน (ที่มีfind
การใช้งานบางอย่าง) จะไม่ตรงกับStéphane
ที่*
เป็น 0 หรือมากกว่าตัวอักษรและ 0xe9 ไม่ใช่ตัวอักษร
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
ของฉันfind
(เมื่อผลลัพธ์ไปยังเทอร์มินัล) แสดง 0xe9 ไบต์ที่ไม่ถูกต้องดังกล่าว?
ข้างต้น คุณจะเห็นว่าSt<0xe9>phane/Chazelas
ไม่ใช่prune
d
คุณสามารถหลีกเลี่ยงได้โดยทำ:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
แต่โปรดทราบว่าจะมีผลกับการตั้งค่าภาษาทั้งหมดfind
และแอปพลิเคชันใด ๆ ที่ทำงาน (เช่นผ่านภาค-exec
แสดง)
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
ตอนนี้ฉันได้รับจริง ๆ-maxdepth 2
แต่ทราบว่าéในStéphaneที่สองถูกเข้ารหัสอย่างถูกต้องใน UTF-8 แสดงเป็น??
อย่างไร 0xc3 0xa9 ไบต์ (ถือว่าเป็นอักขระสองตัวที่ไม่ได้กำหนดใน C ตำแหน่งที่ตั้ง) ของการเข้ารหัส UTF-8 ของé ไม่ใช่อักขระที่พิมพ์ได้ใน C locale
และถ้าฉันเพิ่ม a ลงไป-name '????????'
ฉันจะได้ค่าStéphaneผิด (อันที่เข้ารหัสใน iso8859-1)
หากต้องการนำไปใช้กับเส้นทางที่กำหนดเองแทนคุณ.
จะต้อง:
find some/dir/. ! -name . -prune ...
สำหรับ-mindepth 1 -maxdepth 1
หรือ:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
-maxdepth 2
สำหรับ
ฉันจะยังคงทำ:
(cd -P -- "$dir" && find . ...)
ก่อนเพราะนั่นทำให้เส้นทางสั้นลงซึ่งทำให้มีโอกาสน้อยที่จะวิ่งเข้าไปในเส้นทางยาวเกินไปหรือหาเรื่องรายการปัญหาที่ยาวเกินไปแต่ยังต้องหลีกเลี่ยงข้อเท็จจริงที่find
ไม่สามารถรองรับอาร์กิวเมนต์เส้นทางโดยพลการ (ยกเว้น-f
กับ FreeBSD find
) เนื่องจากจะทำให้หายใจไม่ออก ค่า$dir
ชอบ!
หรือ-print
...
-o
รวมกันด้วยการปฏิเสธเป็นเคล็ดลับเรื่องธรรมดาที่จะเรียกใช้สองชุดเป็นอิสระจาก-condition
/ ใน-action
find
หากคุณต้องการทำงาน-action1
กับการประชุมไฟล์-condition1
และเป็นอิสระ-action2
ในการประชุมไฟล์-condition2
คุณไม่สามารถทำได้:
find . -condition1 -action1 -condition2 -action2
เช่น-action2
เดียวกับที่จะเรียกใช้สำหรับไฟล์ที่ตรงตามเงื่อนไขทั้งสอง
มิได้:
find . -contition1 -action1 -o -condition2 -action2
ในฐานะที่-action2
จะไม่ถูกเรียกใช้ไฟล์ที่ตอบสนองทั้งเงื่อนไข
find . \( ! -condition1 -o -action1 \) -condition2 -action2
ทำงานตามที่\( ! -condition1 -o -action1 \)
ต้องการจะแก้ไขเป็นจริงสำหรับทุกไฟล์ ที่ถือว่า-action1
เป็นกระทำ (เช่น-prune
, -exec ... {} +
) ที่เสมอกลับจริง สำหรับการดำเนินการเช่น-exec ... \;
นั้นอาจส่งคืนค่าเท็จคุณอาจต้องการเพิ่มรายการอื่น-o -something
ที่-something
ไม่เป็นอันตราย แต่ส่งกลับค่าจริงเช่น-true
ใน GNU find
หรือ-links +0
หรือ -name '*'
(ถึงแม้ว่าจะบันทึกปัญหาเกี่ยวกับอักขระที่ไม่ถูกต้องด้านบน)
-depth -2
,-depth 1
... สามารถมองเห็นวิธีการได้ดีกว่า GNU's-maxdepth
/-mindepth