ฉันจะรับจำนวนไฟล์ในไดเรกทอรีโดยใช้บรรทัดคำสั่งได้อย่างไร


193

ฉันมีไดเรกทอรีที่มีไฟล์จำนวนมาก ฉันไม่เห็นlsสวิตช์ให้การนับ มีเวทมนตร์บรรทัดคำสั่งเพื่อรับจำนวนไฟล์หรือไม่



tree . | tailหรือหากtree -a . | tailต้องการรวมไฟล์ / dirs ที่ซ่อนไว้treeจะเรียกซ้ำหากเป็นสิ่งที่คุณต้องการ
CodyChan

คำตอบ:


239

การใช้คำจำกัดความกว้าง ๆ ของ "ไฟล์"

ls | wc -l

(โปรดทราบว่าจะไม่นับไฟล์ที่ซ่อนอยู่และถือว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่)

ในการรวมไฟล์ที่ซ่อนอยู่ (ยกเว้น.และ..) และหลีกเลี่ยงปัญหาเกี่ยวกับอักขระบรรทัดใหม่ทางบัญญัติคือ:

find . ! -name . -prune -print | grep -c /

หรือเรียกซ้ำ:

find .//. ! -name . -print | grep -c //

23
wcเป็นโปรแกรม "นับจำนวนคำ" -lสวิทช์ทำให้เกิดการนับจำนวนบรรทัด lsในกรณีนี้ก็นับเส้นในการส่งออกจาก นี่คือวิธีที่ฉันได้รับการสอนเสมอเพื่อให้ได้จำนวนไฟล์สำหรับไดเรกทอรีที่กำหนดเช่นกัน
Sandy

20
โปรดเพิ่มหมายเหตุที่lsจะเกิดขึ้นls -1หากเอาต์พุตเป็นไพพ์
lesmana

6
ที่ไม่ได้รับทุกสิ่งในไดเรกทอรี - คุณพลาดจุดไฟล์และรวบรวมคู่บรรทัดเพิ่มเติมด้วย ไดเรกทอรีว่างจะยังคงส่งคืน 1 บรรทัด และถ้าคุณโทรls -laคุณจะได้รับสามบรรทัดในไดเรกทอรี คุณต้องการls -lA | wc -lข้ามรายการ.และ ..อย่างไรก็ตามคุณจะยังคงเป็นแบบหนึ่งต่อหนึ่ง

1
ไดเรกทอรีว่างเปล่าส่งคืนค่า 0 สำหรับฉัน
James Roth

2
แนวทางที่ถูกต้องซึ่งจะไม่นับจำนวนไฟล์ที่มีบรรทัดใหม่ในชื่อจะเป็นเช่นนี้: ls -q | wc -l- แม้ว่าโปรดทราบว่าไฟล์ที่ซ่อนอยู่จะยังไม่ถูกนับด้วยวิธีการนี้และไดเรกทอรีนั้นจะถูกนับ
godlygeek

31

สำหรับคำจำกัดความที่แคบของไฟล์:

 find . -maxdepth 1 -type f | wc -l

และแน่นอนว่าคุณสามารถละเว้นการ-maxdepth 1นับไฟล์แบบเรียกซ้ำ (หรือปรับตามความลึกของการค้นหาสูงสุดที่ต้องการ)
user7089

1
หากคุณมีไฟล์ที่มีชื่อขึ้นบรรทัดใหม่วิธีการนี้จะนับผิดสองครั้ง
godlygeek

7
วิธีการแก้ไขที่จะไม่นับไฟล์สองครั้งด้วยการขึ้นบรรทัดใหม่ในชื่อจะเป็นเช่นนี้:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1 อนุญาตให้ไฟล์ที่ซ่อนอยู่และไม่สนใจไดเรกทอรี
Michael Durrant

14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: หมายเหตุ ls - <number-one> | wc - <letter-l>


10
เวอร์ชันส่วนใหญ่lsทำ-1โดยอัตโนมัติเมื่อเอาต์พุตไปยังไพพ์
Dennis Williamson

3
@ เดนนิสที่น่าสนใจฉันไม่ทราบว่าแอปพลิเคชันสามารถบอกได้ว่าการส่งออกกำลังจะไปป์
xenoterracide

1
ฉัน + เวอร์ชันนี้เนื่องจากมีความชัดเจนมากขึ้น แม้ว่าใช่ ls จะใช้ -1 ถ้ามันถูกไพพ์ (ลองใช้: ls | cat) ฉันพบว่าไวยากรณ์ -1 ชัดเจนขึ้น
เกบ

3
@xenoterracide: ใน Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson

2
ในการทดสอบของฉันมันเร็วกว่ามากที่จะให้ตัวเลือก -f เพื่อหลีกเลี่ยงการเรียงลำดับชื่อไฟล์ น่าเสียดายที่คุณยังได้รับคำตอบที่ผิดถ้าชื่อไฟล์ของคุณมีการขึ้นบรรทัดใหม่
ซามูเอลเอ็ดวินวอร์ด

10

อาจเป็นคำตอบที่สมบูรณ์ที่สุดโดยใช้ls/ wcคู่คือ

ls -Aq | wc -l

หากคุณต้องการนับไฟล์ดอทและ

ls -q | wc -l

มิฉะนั้น.

  • -Aคือการนับไฟล์จุด แต่ละเว้นและ...
  • -qทำให้lsแทนที่อักขระ nongraphic อักขระขึ้นบรรทัดใหม่โดยเฉพาะด้วย?การสร้างเอาต์พุต 1 บรรทัดสำหรับแต่ละไฟล์

ในการรับเอาท์พุทหนึ่งบรรทัดจากlsในเทอร์มินัล (เช่นโดยไม่ต้องปิปเข้าไปwc) -1จะต้องเพิ่มตัวเลือก

(พฤติกรรมของlsการทดสอบกับ coreutils 8.23)


2
อย่างที่คุณบอกว่า-1ไม่จำเป็น สำหรับ"มันจัดการบรรทัดใหม่ในชื่อไฟล์อย่างสมเหตุสมผลด้วยเอาต์พุตคอนโซล"นี่เป็นเพราะ-qสวิตช์ (ซึ่งคุณควรใช้แทน-bเพราะมันพกพาได้) ซึ่ง"บังคับแต่ละอินสแตนซ์ของอักขระชื่อไฟล์ที่ไม่สามารถพิมพ์ได้และตัวอักษร <tab> เป็นอักขระ <question-mark> ('?') การใช้งานอาจมีตัวเลือกนี้เป็นค่าเริ่มต้นหากเอาต์พุตเป็นอุปกรณ์ปลายทาง " ดังนั้นเช่นls -Aq | wc -lการนับไฟล์ / dirs ทั้งหมดหรือls -qp | grep -c /นับเฉพาะ dirs ที่ไม่ได้ซ่อนเป็นต้น
don_crissti

ขอบคุณสำหรับข้อมูลของคุณ เปลี่ยนแปลงไป-b -q
Frax

7

หากคุณรู้ว่าไดเรกทอรีปัจจุบันมีไฟล์ที่ไม่ซ่อนไว้อย่างน้อยหนึ่งไฟล์:

set -- *; echo "$#"

เห็นได้ชัดว่านี่คือ generalizing ใด ๆ glob

ในสคริปต์สิ่งนี้มีผลข้างเคียงที่โชคร้ายในบางครั้งของการเขียนทับพารามิเตอร์ตำแหน่ง คุณสามารถแก้ไขได้โดยใช้ subshell หรือฟังก์ชั่น (เวอร์ชัน Bourne / POSIX) เช่น:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

$(ls -d -- * | wc -l)วิธีการแก้ปัญหาทางเลือกคือ หาก glob เป็นคำสั่งที่สามารถลงไป* $(ls | wc -l)การแยกวิเคราะห์ผลลัพธ์ของการlsทำให้ฉันไม่สบายใจเสมอ แต่ที่นี่ควรจะทำงานตราบใดที่ชื่อไฟล์ของคุณไม่มีการขึ้นบรรทัดใหม่หรือlsหนีออกมาได้ และ$(ls -d -- * 2>/dev/null | wc -l)มีข้อได้เปรียบในการจัดการกับกรณีของก้อนกลมที่ไม่ได้จับคู่อย่างสง่างาม (กล่าวคือมันคืนค่า 0 ในกรณีนั้นในขณะที่set *วิธีการนั้นต้องการการทดสอบที่ยุ่งเหยิงหากก้อนกลมอาจว่างเปล่า)

$(ls -d ./* | grep -c /)ถ้าชื่อไฟล์อาจจะมีตัวอักษรขึ้นบรรทัดใหม่อีกทางเลือกหนึ่งคือการใช้

โซลูชันใด ๆ เหล่านั้นที่พึ่งพาการส่งผ่านการขยายของ glob ไปlsอาจล้มเหลวพร้อมกับรายการอาร์กิวเมนต์ที่ผิดพลาดนานเกินไปหากมีไฟล์ที่ตรงกันจำนวนมาก


1
คุณต้องการสร้างพารามิเตอร์ตำแหน่ง 13,923 จริงหรือไม่ และคุณควรจะทำให้ตัวแปรท้องถิ่นของคุณlocalหรือขจัดความมันeval $1=$#หรือเพียงแค่ใช้และทำecho $# number_of_files=$(count_words *)
Dennis Williamson

1
@Dennis: ส่วนหนึ่งของจุดเพื่อหลีกเลี่ยงการฟอร์ก ฉันคิดว่านั่นไม่ใช่ความกังวลในศตวรรษที่ 21 ตกลงฉันยอมรับว่าฉันไม่สนใจเกี่ยวกับเชลล์ที่ไม่ใช่ POSIX อีกต่อไปดังนั้นฉันสามารถหลีกเลี่ยงตัวแปรชั่วคราวได้
Gilles

ทำไมคุณถึงลบออก$#(คุณไม่ได้ทำอย่างนั้นมาก่อนการแก้ไข)
Dennis Williamson

@Dennis: ฉันยังคงหลีกเลี่ยงส้อม (ดีมันจะสร้างความแตกต่างในเครื่องที่มี CPU ช้าเช่นเราเตอร์) $1และผ่านชื่อตัวแปรเป็น สิ่งที่ฉันต้องการนับคือจำนวนพารามิเตอร์ที่ไม่ใช่พารามิเตอร์แรก (ฉันไม่สามารถใช้shiftเพราะฉันต้องการให้ชื่อตัวแปรอยู่รอบ ๆ ) (อืมตอนนี้ถ้าคุณถามเกี่ยวกับบรรทัดแรก ... )
Gilles

@Dennis: ลองคิดดูสิฉันสามารถใช้งานได้shiftถ้าฉันถูกเวลา
Gilles

7

ฉันพบว่าdu --inodesมีประโยชน์ แต่ฉันไม่แน่ใจว่าduต้องใช้เวอร์ชันใด มันควรจะเป็นอย่างมากเร็วกว่าวิธีการทางเลือกใช้และfindwc

บน Ubuntu 17.10 ทำงานได้ดังต่อไปนี้:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

รวมกับ| sort -nrการเรียงลำดับจากมากไปน้อยตามจำนวนของ inodes ที่มี


5

ในขณะที่ใช้คู่ ls / wc หากเราเพิ่ม -U มันจะเร็วขึ้นมาก (อย่าเรียงลำดับ)

ls -AqU | wc -l

1
-Uเป็นเฉพาะ GNU แม้ว่า
Stéphane Chazelas

4

หลังจากติดตั้งคำสั่ง tree ให้พิมพ์:

tree

หากคุณต้องการไฟล์ที่ซ่อนอยู่ด้วย:

tree -a

หากคุณใช้ Debian / Mint / Ubuntu Linux ให้พิมพ์คำสั่งต่อไปนี้เพื่อติดตั้งคำสั่ง tree:

sudo apt-get install tree

อ็อพชัน -L ใช้สำหรับการระบุระดับการแสดงผลสูงสุดของแผนผังไดเร็กทอรี คำสั่ง tree ไม่เพียง แต่นับจำนวนไฟล์เท่านั้น แต่ยังรวมถึงจำนวนไดเรคทอรี่โดยพิจารณาถึงระดับไดเรคทอรีตามที่คุณต้องการ


เมื่อฉันพิมพ์ tree ฉันจะได้ผลลัพธ์ของ tree ไปที่หน้าจอของไดเร็กตอรี่ที่ฉันอยู่ แต่ฉันไม่สามารถดูได้ว่าจำนวนไฟล์ถูกแสดงที่ใด
charlesdarwin

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1จะทำให้ไม่เกิดซ้ำfindเรียกซ้ำโดยค่าเริ่มต้น
  • -type f จะรวมไฟล์เท่านั้น
  • -printf .เป็นสัมผัสที่น่ารัก มันพิมพ์จุดสำหรับแต่ละไฟล์แทนชื่อไฟล์และตอนนี้สามารถจัดการกับชื่อไฟล์ใด ๆ และยังบันทึกข้อมูล เราแค่ต้องนับจุด :)
  • | wc -c นับจำนวนตัวอักษร

1

ไม่มีท่อไม่มีการคัดลอกสตริงไม่มีส้อมเพียงแค่ทุบตีหนึ่งซับ

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
ให้ค่า 1 หากไม่มีไฟล์ในไดเร็กทอรี ไม่นับไฟล์นับจำนวนไฟล์และไดเรกทอรี
สตีฟ

1

นี่เป็นอีกเทคนิคหนึ่งในแนวของGilles ที่โพสต์ :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

ซึ่งสร้างอาร์เรย์ที่มีองค์ประกอบ 13,923 (ถ้านั่นคือจำนวนไฟล์ที่มี)


จุดประสงค์ของcอาเรย์นั้นคืออะไร? word_count() { echo "$#"; }จะเพียงพอ จุดของการแก้ปัญหา @Gilles คือการเก็บจำนวนในตัวแปรกลับเพื่อหลีกเลี่ยงการใช้การทดแทนคำสั่ง (ซึ่งเกี่ยวข้องกับส้อมและท่อในเปลือกอื่น ๆ กว่า ksh93)
Stéphane Chazelas

1
find . -type f -maxdepth 1 |  wc -l 

นี่สามารถแสดงรายการไฟล์ในไดเรกทอรีปัจจุบันเท่านั้น


find . -type fจะค้นหาไฟล์ในไดเรกทอรีปัจจุบันและซ้ำในไดเรกทอรีย่อย
dhag



0

ปรับปรุงคำตอบที่ให้ไว้ก่อนหน้า แต่คราวนี้ทำอย่างชัดเจน

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

มันคุ้มค่าที่จะสังเกตเห็นการใช้งานของบางคำสั่งเช่นรักและtail cutนอกจากนี้โปรดทราบว่าต้นไม้จะไม่สามารถใช้ได้ตามค่าเริ่มต้น คำสั่งด้านบนแรกจับข้อมูลเกี่ยวกับไดเรกทอรีที่ระดับ 1 จากนั้นรับบรรทัดสุดท้ายtail -n 1ที่เป้าหมายของเราคือและจบลงด้วยcutการใช้คำที่สาม

ตัวอย่างเช่นค้นหาใน/:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

ถ้าเช่นนั้นถามเกี่ยวกับจำนวนไดเรกทอรี?


0

บน Linux เพื่อทำให้คำสั่งมีความสมบูรณ์และจัดการไฟล์ที่อาจมีการขึ้นบรรทัดใหม่ในชื่อให้ใช้:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

นี้ช่วยเราจากความเจ็บปวดของการแยกlsเอาท์พุท


ที่เกี่ยวข้อง:


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.