ฉันจะนับซ้ำไฟล์ในไดเรกทอรี Linux ได้อย่างไร
ฉันพบสิ่งนี้:
find DIR_NAME -type f ¦ wc -l
แต่เมื่อฉันเรียกใช้มันกลับข้อผิดพลาดต่อไปนี้
ค้นหา: พา ธ ต้องนำหน้านิพจน์: ¦
*
กับอักขระ ASCII "เครื่องหมายดอกจัน" แต่ "คูณ" ในบริบทอื่น ๆ
ฉันจะนับซ้ำไฟล์ในไดเรกทอรี Linux ได้อย่างไร
ฉันพบสิ่งนี้:
find DIR_NAME -type f ¦ wc -l
แต่เมื่อฉันเรียกใช้มันกลับข้อผิดพลาดต่อไปนี้
ค้นหา: พา ธ ต้องนำหน้านิพจน์: ¦
*
กับอักขระ ASCII "เครื่องหมายดอกจัน" แต่ "คูณ" ในบริบทอื่น ๆ
คำตอบ:
สิ่งนี้น่าจะใช้ได้:
find DIR_NAME -type f | wc -l
คำอธิบาย:
-type f
เพื่อรวมไฟล์เท่านั้น|
( และไม่ใช่¦
) เปลี่ยนทิศทางfind
เอาต์พุตwc
มาตรฐานของคำสั่งไปยังอินพุตมาตรฐานของคำสั่งwc
(ย่อมาจากการนับจำนวนคำ) นับบรรทัดใหม่คำและไบต์บนอินพุต ( docs )-l
เพื่อนับแค่บรรทัดใหม่หมายเหตุ:
DIR_NAME
ด้วย.
เพื่อรันคำสั่งในโฟลเดอร์ปัจจุบัน-type f
ไดเรกทอรีที่จะรวม (และ symlink) ในการนับคำอธิบายว่าทำไมตัวอย่างของคุณถึงไม่ทำงาน:
ในคำสั่งที่คุณแสดงคุณไม่ได้ใช้ "Pipe" ( |
) เพื่อเชื่อมต่อสองคำสั่ง แต่แถบที่แตก ( ¦
) ซึ่งเชลล์ไม่รู้จักว่าเป็นคำสั่งหรือสิ่งที่คล้ายกัน นั่นเป็นเหตุผลที่คุณได้รับข้อความแสดงข้อผิดพลาด
f
ใน-type f
ยืนสำหรับไฟล์และwc -l
คำสายนับ
-type f
ไดเรกทอรีที่จะรวมในการนับ
-print
ธง
-print0
แฟล็ก
wc
มีตัวเลือกในการอ่านรายการยกเลิก ดูคำตอบของฉันสำหรับทางเลือก
สำหรับไดเรกทอรีปัจจุบัน:
find -type f | wc -l
.
find .
หากคุณต้องการรายละเอียดจำนวนไฟล์ในแต่ละ dir ภายใต้ dir ปัจจุบันของคุณ:
for i in */ .*/ ; do
echo -n $i": " ;
(find "$i" -type f | wc -l) ;
done
ที่สามารถไปทั้งหมดในบรรทัดเดียวแน่นอน วงเล็บจะชี้แจงwc -l
ว่าควรจะดูเอาต์พุตใด ( find $i -type f
ในกรณีนี้)
find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' i ; do
แก้ไข ดูฉันจะอ่านไฟล์ (data stream, variable) ทีละบรรทัด (และ / หรือ field-by-field) ได้อย่างไร?
find
ลูปนอกเป็นเพียงภาวะแทรกซ้อนที่ไม่จำเป็น for i in */
; do`
คุณสามารถใช้ได้
$ tree
หลังจากติดตั้งแพ็คเกจต้นไม้ด้วย
$ sudo apt-get install tree
(บนเครื่อง Linux Debian / Mint / Ubuntu)
คำสั่งไม่เพียงแสดงจำนวนไฟล์เท่านั้น แต่ยังรวมถึงจำนวนไดเรกทอรีด้วย ตัวเลือก - L สามารถใช้เพื่อระบุระดับการแสดงผลสูงสุด (ซึ่งโดยค่าเริ่มต้นคือความลึกสูงสุดของโครงสร้างไดเรกทอรี)
ไฟล์ที่ซ่อนสามารถรวมได้ด้วยการจัดหา-a
ตัวเลือก
-a
ตัวเลือกเพื่อรวมไว้
brew
และเรียกกว่าที่หลังจากทำงานbrew install tree
brew update
บนคอมพิวเตอร์ของฉันrsync
เร็วกว่าfind | wc -l
คำตอบที่ยอมรับเล็กน้อย:
$ rsync --stats --dry-run -ax /path/to/dir /tmp
Number of files: 173076
Number of files transferred: 150481
Total file size: 8414946241 bytes
Total transferred file size: 8414932602 bytes
บรรทัดที่สองมีจำนวนไฟล์ 150,481 ในตัวอย่างข้างต้น เป็นโบนัสคุณจะได้รับขนาดรวมเช่นกัน (เป็นไบต์)
หมายเหตุ:
--dry-run
(หรือ-n
สั้น ๆ ) เป็นสิ่งสำคัญที่จะไม่ถ่ายโอนไฟล์จริง!-x
ตัวเลือกเพื่อ "ไม่ข้ามขอบเขตระบบไฟล์" ซึ่งหมายความว่าถ้าคุณดำเนินการ/
และคุณมีฮาร์ดดิสก์ภายนอกติดอยู่มันจะนับเฉพาะไฟล์ในพาร์ติชันรากfind ~ -type f | wc -l
ใช้เวลา 1.7 / 0.5 / 1.33 วินาที (จริง / ผู้ใช้ / sys) rsync --stats --dry-run -ax ~ /xxx
ใช้เวลา 4.4 / 3.1 / 2.1 วินาที มีไว้สำหรับประมาณ 500,000 ไฟล์บน SSD
Number of files: 487 (reg: 295, dir: 192)
rsync version 2.6.9 protocol version 29
เนื่องจากชื่อไฟล์ใน UNIX อาจมีการขึ้นบรรทัดใหม่ (ใช่, การขึ้นบรรทัดใหม่) wc -l
อาจนับจำนวนไฟล์มากเกินไป ฉันจะพิมพ์จุดสำหรับทุกไฟล์แล้วนับจำนวนจุด:
find DIR_NAME -type f -printf "." | wc -c
เมื่อรวมคำตอบหลายข้อเข้าด้วยกันแล้วทางออกที่มีประโยชน์ที่สุดน่าจะเป็น:
find . -maxdepth 1 -type d -print0 |
xargs -0 -I {} sh -c 'echo -e $(find "{}" -printf "\n" | wc -l) "{}"' |
sort -n
มันสามารถจัดการกับสิ่งแปลก ๆ เช่นชื่อไฟล์ที่มีวงเล็บช่องว่างและแม้กระทั่งบรรทัดใหม่ นอกจากนี้ยังเรียงลำดับผลลัพธ์ตามจำนวนไฟล์
คุณสามารถเพิ่มจำนวนหลังจาก-maxdepth
ได้รับการนับไดเรกทอรีย่อยด้วย โปรดทราบว่าการดำเนินการนี้อาจใช้เวลานานโดยเฉพาะอย่างยิ่งหากคุณมีโครงสร้างไดเรกทอรีที่ซ้อนกันสูงร่วมกับ-maxdepth
จำนวนที่
สูง
echo -e
อะไร ฉันเดาว่าคุณใส่มันเพื่อพับบรรทัดใหม่ใด ๆ แต่มันจะรวมช่องว่างที่ผิดปกติอื่น ๆ และพยายามที่จะขยายอักขระตัวแทนใด ๆ ที่แสดงคำต่อคำในชื่อไฟล์ ฉันจะไปกับสิ่งที่ชอบfind .* * -type d -execdir sh -c 'find . -type f -printf "\n" | wc -l; pwd'
และอยู่กับความผิดปกติใด ๆ ในผลลัพธ์หรืออาจเล่นกับ Bash printf "%q"
เพื่อพิมพ์ชื่อไดเรกทอรี
หากคุณต้องการทราบจำนวนไฟล์และไดเรกทอรีย่อยที่มีอยู่จากไดเรกทอรีการทำงานปัจจุบันคุณสามารถใช้หนึ่งซับเอกสาร
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find {} | wc -l) {}' | sort -n
สิ่งนี้จะทำงานในรสชาติของ GNU และเพียงละเว้น -e จากคำสั่ง echo สำหรับ BSD linux (เช่น OSX)
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find "{}" | wc -l) "{}"' | sort -n
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} | wc -l) \\t {}' | sort -rn | less
echo -e
(หรือเพียง `echo` ในความคิดเห็นก่อนหน้านี้) ในชื่อไดเรกทอรีที่ไม่มีการอ้างอิงเป็นการค้าปัญหาหนึ่งสำหรับอีกปัญหาหนึ่ง
หากคุณต้องการหลีกเลี่ยงกรณีที่มีข้อผิดพลาดไม่อนุญาตให้wc -l
ดูไฟล์ที่มีบรรทัดใหม่ (ซึ่งจะนับเป็น 2 ไฟล์)
เช่นพิจารณากรณีที่เรามีไฟล์เดียวที่มีอักขระ EOL เดียวในนั้น
> mkdir emptydir && cd emptydir
> touch $'file with EOL(\n) character in it'
> find -type f
./file with EOL(?) character in it
> find -type f | wc -l
2
เนื่องจากอย่างน้อย gnu wc
ไม่ปรากฏว่ามีตัวเลือกในการอ่าน / นับรายการที่สิ้นสุดด้วยค่า null (ยกเว้นจากไฟล์) ทางออกที่ง่ายที่สุดคือการไม่ผ่านชื่อไฟล์ แต่มีเอาต์พุตแบบคงที่ทุกครั้งที่พบไฟล์เช่น ในไดเรกทอรีเดียวกันกับด้านบน
> find -type f -exec printf '\n' \; | wc -l
1
หรือถ้าคุณfind
รองรับมัน
> find -type f -printf '\n' | wc -l
1
ncdu
คุณสามารถใช้คำสั่ง มันจะนับซ้ำจำนวนไฟล์ในไดเรกทอรี Linux นี่คือตัวอย่างของเอาต์พุต:
มันมีแถบความคืบหน้าซึ่งจะสะดวกถ้าคุณมีไฟล์จำนวนมาก:
วิธีติดตั้งบน Ubuntu:
sudo apt-get install -y ncdu
เกณฑ์มาตรฐาน: ฉันใช้https://archive.org/details/cv_corpus_v1.tar (ไฟล์ 380390, 11 GB) เป็นโฟลเดอร์ที่ต้องนับจำนวนไฟล์
find . -type f | wc -l
: ประมาณ 1m20s เพื่อให้เสร็จสมบูรณ์ncdu
: ประมาณ 1m20s เพื่อให้เสร็จสมบูรณ์find . -type f | wc -l
ncdu
find
อยู่ภายใต้ฝากระโปรงหน้าการดำเนินการมากขึ้นหรือน้อยเหมือนกันสายระบบเป็นซึ่งเป็นแบ็กเอนด์สำหรับdu
ncdu
เพียงแค่มัดพวกเขา
tree $DIR_PATH | tail -1
ตัวอย่างผลลัพธ์:
ไดเรกทอรี 5309 ไฟล์ 2122
ls -1 | wc -l
เพื่อตรวจสอบจำนวนไฟล์ที่มีอยู่ในไดเรกทอรีปัจจุบันใส่ใน นี้จะใช้wc
ในการทำการนับจำนวนของเส้นที่ในการส่งออกของ(-l)
ls -1
มันไม่นับ dotfiles โปรดทราบว่าls -l
(นั่นคือ "L" แทนที่จะเป็น "1" เหมือนในตัวอย่างก่อนหน้านี้) ซึ่งฉันใช้ใน HOWTO รุ่นก่อนหน้านี้จะให้ไฟล์กับคุณมากกว่าหนึ่งจำนวนจริง ขอบคุณ Kam Nejad สำหรับประเด็นนี้
หากคุณต้องการนับเฉพาะไฟล์และไม่รวมลิงก์สัญลักษณ์ (เป็นเพียงตัวอย่างของสิ่งที่คุณสามารถทำได้) คุณสามารถใช้ls -l | grep -v ^l | wc -l
(นั่นคือ "L" ไม่ใช่ "1" ในเวลานี้เราต้องการรายชื่อ "ยาว" ที่นี่) . grep
ตรวจสอบบรรทัดที่ขึ้นต้นด้วย "l" (ระบุลิงค์) และทิ้งบรรทัดนั้น (-v)
ความเร็วสัมพัทธ์: "ls -1 / usr / bin / | wc -l" ใช้เวลาประมาณ 1.03 วินาทีในการโหลด 486SX25 (/ usr / bin / บนเครื่องนี้มีไฟล์ 355) " ls -l /usr/bin/ | grep -v ^l | wc -l
" ใช้เวลาประมาณ 1.19 วินาที
ที่มา: http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html
ls -l
ต้องทำstat
syscall ในทุกไฟล์เพื่ออ่านขนาดคุณสมบัติ mtime และคุณสมบัติอื่น ๆ ซึ่งช้า ในไดเรกทอรีใหญ่ (100.000+ ไฟล์) ทำงานls -l
อาจใช้เวลาหลายนาที ls -1 | wc -l
ดังนั้นเพื่อให้นับเฉพาะไฟล์เสมอการใช้งาน
หากสิ่งที่คุณต้องการคือการนับประเภทไฟล์ที่ เรียกซ้ำคุณสามารถทำได้:
find YOUR_PATH -name '*.html' -type f | wc -l
-l
เป็นเพียงการแสดงจำนวนบรรทัดในผลลัพธ์
ด้วยทุบตี:
สร้างอาร์เรย์ของรายการด้วย () และรับจำนวนด้วย #
FILES=(./*); echo ${#FILES[@]}
ตกลงที่ไม่นับไฟล์ซ้ำ แต่ฉันต้องการที่จะแสดงตัวเลือกที่ง่ายก่อน กรณีการใช้งานทั่วไปอาจใช้เพื่อสร้างการสำรองข้อมูลแบบโรลโอเวอร์ของไฟล์ สิ่งนี้จะสร้าง logfile.1, logfile.2, logfile.3 เป็นต้น
CNT=(./logfile*); mv logfile logfile.${#CNT[@]}
จำนวนการเรียกซ้ำที่globstar
เปิดใช้งานbash 4+ (ตามที่กล่าวถึงโดย @tripleee)
FILES=(**/*); echo ${#FILES[@]}
ในการรับจำนวนไฟล์ซ้ำเรายังคงสามารถใช้ find ในวิธีเดียวกันได้
FILES=(`find . -type f`); echo ${#FILES[@]}
**/*
การแจงนับซ้ำ ยังคงมีประสิทธิภาพน้อยกว่าfind
ในไดเรกทอรีขนาดใหญ่เนื่องจากเชลล์ต้องเรียงลำดับไฟล์ในแต่ละไดเรกทอรี
สำหรับไดเรกทอรีที่มีช่องว่างในชื่อ ... (ขึ้นอยู่กับคำตอบที่หลากหลายด้านบน) - พิมพ์ชื่อไดเรกทอรีซ้ำด้วยจำนวนไฟล์ภายใน:
find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
ตัวอย่าง (จัดรูปแบบเพื่อให้สามารถอ่านได้):
pwd
/mnt/Vancouver/Programming/scripts/claws/corpus
ls -l
total 8
drwxr-xr-x 2 victoria victoria 4096 Mar 28 15:02 'Catabolism - Autophagy; Phagosomes; Mitophagy'
drwxr-xr-x 3 victoria victoria 4096 Mar 29 16:04 'Catabolism - Lysosomes'
ls 'Catabolism - Autophagy; Phagosomes; Mitophagy'/ | wc -l
138
## 2 dir (one with 28 files; other with 1 file):
ls 'Catabolism - Lysosomes'/ | wc -l
29
โครงสร้างไดเรกทอรีแสดงภาพได้ดีขึ้นโดยใช้tree
:
tree -L 3 -F .
.
├── Catabolism - Autophagy; Phagosomes; Mitophagy/
│ ├── 1
│ ├── 10
│ ├── [ ... SNIP! (138 files, total) ... ]
│ ├── 98
│ └── 99
└── Catabolism - Lysosomes/
├── 1
├── 10
├── [ ... SNIP! (28 files, total) ... ]
├── 8
├── 9
└── aaa/
└── bbb
3 directories, 167 files
man find | grep mindep
-mindepth levels
Do not apply any tests or actions at levels less than levels
(a non-negative integer). -mindepth 1 means process all files
except the starting-points.
ls -p | grep -v /
(ใช้ด้านล่าง) มาจากคำตอบ 2 ที่/unix/48492/list-only-regular-files-but-not-directories-in-current-directory
find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Catabolism - Lysosomes: 28
./Catabolism - Lysosomes/aaa: 1
Applcation: ฉันต้องการค้นหาจำนวนไฟล์สูงสุดในไดเรกทอรีหลายร้อยไดเรกทอรี (ทุกความลึก = 1) [เอาท์พุทด้านล่างในรูปแบบอีกครั้งเพื่อให้อ่านง่าย]:
date; pwd
Fri Mar 29 20:08:08 PDT 2019
/home/victoria/Mail/2_RESEARCH - NEWS
time find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done > ../../aaa
0:00.03
[victoria@victoria 2_RESEARCH - NEWS]$ head -n5 ../../aaa
./RNA - Exosomes: 26
./Cellular Signaling - Receptors: 213
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Stress - Physiological, Cellular - General: 261
./Ancient DNA; Ancient Protein: 34
[victoria@victoria 2_RESEARCH - NEWS]$ sed -r 's/(^.*): ([0-9]{1,8}$)/\2: \1/g' ../../aaa | sort -V | (head; echo ''; tail)
0: ./Genomics - Gene Drive
1: ./Causality; Causal Relationships
1: ./Cloning
1: ./GenMAPP 2
1: ./Pathway Interaction Database
1: ./Wasps
2: ./Cellular Signaling - Ras-MAPK Pathway
2: ./Cell Death - Ferroptosis
2: ./Diet - Apples
2: ./Environment - Waste Management
988: ./Genomics - PPM (Personalized & Precision Medicine)
1113: ./Microbes - Pathogens, Parasites
1418: ./Health - Female
1420: ./Immunity, Inflammation - General
1522: ./Science, Research - Miscellaneous
1797: ./Genomics
1910: ./Neuroscience, Neurobiology
2740: ./Genomics - Functional
3943: ./Cancer
4375: ./Health - Disease
sort -V
เป็นธรรมชาติ ... ดังนั้นจำนวนไฟล์สูงสุดในไดเรกทอรีใด ๆ (Claws Mail) คือ 4375 ไฟล์ ถ้าฉันกดปุ่มซ้าย ( https://stackoverflow.com/a/55409116/1904943 ) ชื่อไฟล์เหล่านั้น - ชื่อทั้งหมดเป็นตัวเลขเริ่มต้นด้วย 1 ในแต่ละไดเรกทอรี - และรองถึง 5 หลักทั้งหมดฉันควรจะตกลง .
ภาคผนวก
ค้นหาจำนวนไฟล์ทั้งหมดไดเรกทอรีย่อยในไดเรกทอรี
$ date; pwd
Tue 14 May 2019 04:08:31 PM PDT
/home/victoria/Mail/2_RESEARCH - NEWS
$ ls | head; echo; ls | tail
Acoustics
Ageing
Ageing - Calorie (Dietary) Restriction
Ageing - Senescence
Agriculture, Aquaculture, Fisheries
Ancient DNA; Ancient Protein
Anthropology, Archaeology
Ants
Archaeology
ARO-Relevant Literature, News
Transcriptome - CAGE
Transcriptome - FISSEQ
Transcriptome - RNA-seq
Translational Science, Medicine
Transposons
USACEHR-Relevant Literature
Vaccines
Vision, Eyes, Sight
Wasps
Women in Science, Medicine
$ find . -type f | wc -l
70214 ## files
$ find . -type d | wc -l
417 ## subdirectories
ฉันได้เขียนffcntเพื่อเพิ่มความเร็วในการนับไฟล์แบบเรียกซ้ำภายใต้สถานการณ์เฉพาะ: ดิสก์แบบหมุนและระบบไฟล์ที่รองรับการทำแผนที่ขอบเขต
มันสามารถเป็นลำดับความสำคัญได้เร็วกว่าls
หรือfind
ตามแนวทาง แต่ YMMV
มีคำตอบที่ถูกต้องมากมายที่นี่ นี่คืออีก!
find . -type f | sort | uniq -w 10 -c
โดยที่.
โฟลเดอร์จะค้นหาและ10
คือจำนวนอักขระที่จะจัดกลุ่มไดเรกทอรี
ค้นหาประเภท f | ห้องสุขา -l
หรือ (ถ้าไดเรกทอรีเป็นไดเรกทอรีปัจจุบัน)
หา -type f | ห้องสุขา -l
มันจะทำงานได้ดีอย่างสมบูรณ์ ง่าย ๆ สั้น ๆ หากคุณต้องการนับจำนวนไฟล์ที่มีอยู่ในโฟลเดอร์
ls | wc -l
แนวทางอื่นที่มีการกรองสำหรับรูปแบบจะนับโมดูลเคอร์เนล grub ที่มีอยู่ทั้งหมด:
ls -l /boot/grub/*.mod | wc -l
ls -l | grep -e -x -e -dr | wc -l
¦
(ASCII 166) กับแถบแนวตั้ง|
(ASCII 124) ใช้สำหรับท่อยูนิกซ์