user4556274 มีคำตอบอยู่แล้วทำไม คำตอบของฉันทำหน้าที่เพียงเพื่อให้ข้อมูลเพิ่มเติมสำหรับวิธีการนับไฟล์อย่างถูกต้อง
ในชุมชน Unix ความเห็นทั่วไปคือการแยกวิเคราะห์ผลลัพธ์ls
เป็นความคิดที่เลวมากเนื่องจากชื่อไฟล์สามารถมีอักขระควบคุมหรืออักขระที่ซ่อนอยู่ ตัวอย่างเช่นเนื่องจากอักขระขึ้นบรรทัดใหม่ในชื่อไฟล์เราได้ls | wc -l
บอกเราว่ามี 5 บรรทัดในผลลัพธ์ของls
(ซึ่งมี) แต่ในความเป็นจริงมีเพียง 4 ไฟล์ในไดเรกทอรี
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
วิธีที่ # 1: ค้นหาโปรแกรมอรรถประโยชน์
find
คำสั่งซึ่งโดยปกติจะใช้สำหรับการทำงานรอบแยกชื่อไฟล์ที่สามารถช่วยเราได้ที่นี่โดยการพิมพ์หมายเลขไอโหนด ไม่ว่าจะเป็นไดเรกทอรีหรือไฟล์มีเพียงหมายเลขไอโหนดที่ไม่ซ้ำกันเท่านั้น ดังนั้นการใช้-printf "%i\n"
และการยกเว้น.
ผ่านทาง-not -name "."
เราสามารถมีจำนวนไฟล์ที่ถูกต้อง (โปรดทราบว่าการใช้-maxdepth 1
เพื่อป้องกันไม่ให้ซ้ำไปมาในไดเรกทอรีย่อย)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
วิธีที่ # 2: globstar
วิธีที่ง่ายรวดเร็วและพกพาได้ส่วนใหญ่:
$ set -- *
$ echo $#
228
set
คำสั่งจะใช้ในการตั้งค่าพารามิเตอร์ตำแหน่งของเปลือก ( $<INTEGER>
ตัวแปรเช่นในecho $1
) มักใช้เพื่อแก้ไข/bin/sh
ข้อ จำกัด ของอาร์เรย์ที่ขาด รุ่นที่มีการตรวจสอบพิเศษสามารถพบได้ในคำตอบของ Gilleบน Unix & Linux
ในเชลล์ที่สนับสนุนอาร์เรย์เช่นbash
เราสามารถใช้
items=( dir/* )
echo ${#items[@]}
ที่เสนอโดยsteeldriver ในการแสดงความคิดเห็น
เทคนิคคล้ายกับfind
วิธีที่ใช้wc
และ globstar สามารถใช้stat
เพื่อนับจำนวนไอโหนดต่อบรรทัด:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
อีกทางเลือกหนึ่งคือการใช้ตัวแทนในfor
วง (หมายเหตุการทดสอบนี้ใช้ไดเรกทอรีที่แตกต่างกันเพื่อทดสอบว่าวิธีการนี้เข้าสู่ไดเรกทอรีย่อยหรือไม่ซึ่งไม่ใช่ - 16 คือจำนวนรายการที่ตรวจสอบแล้วในฉัน~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
วิธีที่ # 3: ภาษา / ล่ามอื่น ๆ
Python สามารถจัดการกับชื่อไฟล์ที่มีปัญหาผ่านการพิมพ์ความยาวของรายการที่กำหนดให้os.listdir()
ฟังก์ชั่นของฉัน(ซึ่งไม่เรียกซ้ำและจะแสดงรายการในไดเรกทอรีที่กำหนดเป็นอาร์กิวเมนต์เท่านั้น)
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
ดูสิ่งนี้ด้วย
ls | wc -l
จะล้มเหลวหากมีไฟล์ที่มีการขึ้นบรรทัดใหม่ในชื่อไฟล์ นี่คือความยืดหยุ่นที่มากขึ้น:find . -mindepth 1 -maxdepth 1 -printf . | wc -c