คำตอบสั้น ๆ :
\ls -afq | wc -l
(ซึ่งรวมถึง.
และ..
เพื่อลบ 2)
เมื่อคุณแสดงรายการไฟล์ในไดเรกทอรีสามสิ่งทั่วไปอาจเกิดขึ้น:
- การระบุชื่อไฟล์ในไดเรกทอรี นี่เป็นสิ่งที่หลีกเลี่ยงไม่ได้: ไม่มีวิธีนับไฟล์ในไดเรกทอรีโดยไม่ต้องระบุ
- เรียงลำดับชื่อไฟล์ สัญลักษณ์ตัวแทนเชลล์และ
ls
คำสั่งทำเช่นนั้น
- การเรียก
stat
เพื่อดึงข้อมูลเมตาเกี่ยวกับแต่ละรายการไดเรกทอรีเช่นไม่ว่าจะเป็นไดเรกทอรี
# 3 แพงที่สุดเนื่องจากต้องโหลด inode สำหรับแต่ละไฟล์ ในการเปรียบเทียบชื่อไฟล์ทั้งหมดที่จำเป็นสำหรับ # 1 จะถูกเก็บไว้ในบล็อกไม่กี่บล็อก # 2 ทำให้เสียเวลา CPU แต่มักจะไม่ใช่ตัวจัดการดีล
หากไม่มีการขึ้นบรรทัดใหม่ในชื่อไฟล์แบบง่ายls -A | wc -l
จะบอกให้คุณทราบถึงจำนวนไฟล์ที่มีในไดเรกทอรี ระวังว่าถ้าคุณมีนามแฝงls
สิ่งนี้อาจทำให้เกิดการโทรไปที่stat
(เช่นls --color
หรือls -F
จำเป็นต้องรู้ประเภทของไฟล์ที่ต้องมีการเรียกไปstat
) ดังนั้นจากบรรทัดคำสั่งโทรcommand ls -A | wc -l
หรือ\ls -A | wc -l
เพื่อหลีกเลี่ยงนามแฝง
หากมีการขึ้นบรรทัดใหม่ในชื่อไฟล์การขึ้นบรรทัดใหม่จะแสดงรายการหรือไม่ขึ้นอยู่กับตัวแปร Unix coreutils ของ GNU และ BusyBox เริ่มต้นที่จะแสดงขึ้น?
บรรทัดใหม่ดังนั้นมันจึงปลอดภัย
โทรls -f
เพื่อแสดงรายการโดยไม่ต้องเรียงลำดับ (# 2) สิ่งนี้จะเปิดโดยอัตโนมัติ-a
(อย่างน้อยในระบบที่ทันสมัย) -f
ตัวเลือกอยู่ใน POSIX แต่ด้วยสถานะตัวเลือก; การใช้งานส่วนใหญ่รองรับ แต่ไม่ใช่ BusyBox ตัวเลือก-q
จะแทนที่อักขระที่ไม่สามารถพิมพ์ได้รวมถึงการขึ้นบรรทัดใหม่ด้วย?
; มันเป็น POSIX แต่ไม่รองรับโดย BusyBox ดังนั้นให้ละเว้นหากคุณต้องการการสนับสนุน BusyBox โดยมีค่าใช้จ่ายในการโอเวอร์โหลดไฟล์ที่ชื่อมีอักขระขึ้นบรรทัดใหม่
หากไดเรกทอรีไม่มีไดเรกทอรีย่อยรุ่นส่วนใหญ่find
จะไม่เรียกstat
ใช้รายการของตน (การเพิ่มประสิทธิภาพไดเรกทอรีใบไม้: ไดเรกทอรีที่มีจำนวนลิงค์ 2 ไม่สามารถมีไดเรกทอรีย่อยได้ดังนั้นfind
ไม่จำเป็นต้องค้นหาข้อมูลเมตาของรายการยกเว้น เงื่อนไขเช่น-type
ต้องการ) ดังนั้นfind . | wc -l
วิธีพกพาและรวดเร็วในการนับไฟล์ในไดเรกทอรีโดยที่ไดเรกทอรีนั้นไม่มีไดเรกทอรีย่อยและไม่มีชื่อไฟล์ใดมี newline
หากไดเรกทอรีไม่มีไดเรกทอรีย่อย แต่ชื่อไฟล์อาจมีการขึ้นบรรทัดใหม่ให้ลองหนึ่งในไดเรกทอรีเหล่านี้ (ไดเรกทอรีที่สองควรจะเร็วกว่าหากได้รับการสนับสนุน แต่อาจไม่เด่นชัด)
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
ในทางกลับกันอย่าใช้find
ถ้าไดเรกทอรีนั้นมีไดเรกทอรีย่อย: แม้แต่find . -maxdepth 1
เรียกstat
ทุกรายการ (อย่างน้อยด้วย GNU find และ BusyBox find) คุณหลีกเลี่ยงการเรียงลำดับ (# 2) แต่คุณจ่ายราคาของการค้นหา inode (# 3) ที่ฆ่าประสิทธิภาพ
set -- *; echo $#
ในเปลือกไม่มีเครื่องมือภายนอกคุณสามารถเรียกใช้นับไฟล์ในไดเรกทอรีปัจจุบันด้วย นี่เป็นจุดไฟล์ (ไฟล์ที่มีชื่อขึ้นต้นด้วย.
) และรายงาน 1 แทนที่จะเป็น 0 ในไดเรกทอรีว่าง นี่เป็นวิธีที่เร็วที่สุดในการนับไฟล์ในไดเรกทอรีขนาดเล็กเพราะมันไม่จำเป็นต้องเริ่มโปรแกรมภายนอก แต่ (ยกเว้นใน zsh) เสียเวลาสำหรับไดเรกทอรีขนาดใหญ่เนื่องจากขั้นตอนการเรียงลำดับ (# 2)
ใน bash นี่เป็นวิธีที่เชื่อถือได้ในการนับไฟล์ในไดเรกทอรีปัจจุบัน:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
ใน ksh93 นี่เป็นวิธีที่เชื่อถือได้ในการนับไฟล์ในไดเรกทอรีปัจจุบัน:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
ใน zsh นี่เป็นวิธีที่เชื่อถือได้ในการนับไฟล์ในไดเรกทอรีปัจจุบัน:
a=(*(DNoN))
echo $#a
หากคุณมีชุดตัวเลือกให้แน่ใจว่าจะปิด:mark_dirs
a=(*(DNoN^M))
ใน POSIX เชลล์ใด ๆ นี่เป็นวิธีที่เชื่อถือได้ในการนับไฟล์ในไดเรกทอรีปัจจุบัน:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
วิธีการทั้งหมดเหล่านี้เรียงลำดับชื่อไฟล์ยกเว้น zsh one
ls -l|wc -l
จะถูกปิดโดยหนึ่งเนื่องจากบล็อกทั้งหมดในบรรทัดแรกของการls -l
ส่งออก