ฉันจะใช้ตัวนับคำ ( wc
) และการไพพ์เพื่อนับจำนวนไฟล์หรือไดเรกทอรีที่อยู่ใน/usr/bin
ไดเรกทอรีได้อย่างไร
ฉันจะใช้ตัวนับคำ ( wc
) และการไพพ์เพื่อนับจำนวนไฟล์หรือไดเรกทอรีที่อยู่ใน/usr/bin
ไดเรกทอรีได้อย่างไร
คำตอบ:
วิธีการหนึ่งที่จะใช้ประโยชน์จากls
การให้รายการของไฟล์กับเรา แต่เราต้องการให้รายการนี้รับประกันว่าจะแสดงเพียง 1 ไฟล์หรือไดเรกทอรีต่อบรรทัด -1
สวิทช์จะทำเช่นนี้สำหรับเรา
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
สร้างข้อมูลตัวอย่างข้างต้นในไดเรกทอรีว่าง
$ mkdir dir{1..3}
$ touch file{A..C}
ตรวจสอบ:
$ ls
dir1 dir2 dir3 fileA fileB fileC
ตอนนี้เพื่อนับคุณสามารถใช้wc -l
เพื่อนับจำนวนบรรทัดซึ่งสอดคล้องกับไฟล์หรือไดเรกทอรีในls -1
ผลลัพธ์
$ ls -1 | wc -l
6
(โปรดทราบว่าไม่รวมไฟล์ที่ซ่อนอยู่)
ในการนับไฟล์หรือไดเรกทอรีคุณต้องเปลี่ยนชั้นเชิงเล็กน้อย ในกรณีนี้ฉันจะใช้ls -l
เนื่องจากมันแสดงว่าเป็นไดเรกทอรีอะไรและไฟล์ aa
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
จากนั้นเราสามารถใช้grep
เพื่อกรองไดเรกทอรีหรือไดเรกทอรีที่ไม่ชอบ:
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
ตอนนี้ใช้wc -l
อีกครั้งเพื่อนับจำนวนข้างต้น:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
แม้ว่าคุณสามารถหลีกเลี่ยงwc
โดยสิ้นเชิงและการใช้งานgrep
ของ-c
ตัวเลือก:
$ ls -l | grep -c '^d'
(อีกครั้งไฟล์ที่ซ่อนจะไม่รวมโปรดทราบว่าไดเรกทอรีและปกติเป็นไฟล์สองประเภทมีหลายอย่างเช่นเนมไปป์ลิงก์สัญลักษณ์อุปกรณ์ซ็อกเก็ต ... )
หากคุณต้องการที่จะหาไฟล์และไดเรกทอรีซ้ำภายใต้แล้วคุณอาจจะต้องการที่จะใช้กลยุทธ์การเปลี่ยนแปลงอย่างสิ้นเชิงและทำให้การใช้เครื่องมือที่เรียกว่า/usr/bin
find
$ find /usr/bin | wc -l
4632
(แม้ว่าข้างบน/usr/bin
จะรวมอยู่ในการนับ)
เทคนิคเดียวกับที่ฉันใช้ข้างต้นอาจใช้ls
เพื่อทำสิ่งที่คล้ายกัน แต่ls
โดยทั่วไปแล้วไม่ใช่เครื่องมือที่ดีในการแยกวิเคราะห์ผลลัพธ์ find
ในทางตรงกันข้ามถูกสร้างขึ้นสำหรับสิ่งนี้และมีสวิตช์เพื่อค้นหาไฟล์หรือไดเรกทอรี
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(โปรดทราบว่าเวลาfind
นี้รวมถึงไฟล์ที่ซ่อนอยู่ (ยกเว้น.
และ..
))
ฉันไม่เคยเข้าใจเลยว่าทำไมอักขระขึ้นบรรทัดใหม่เป็นอักขระถูกกฎหมายที่จะใช้เมื่อสร้างชื่อไฟล์หรือชื่อไดเรกทอรี ดังนั้นวิธีการที่กล่าวถึงข้างต้นโดยใช้wc
และls
จะไม่โต้แย้งกับสิ่งเหล่านี้ดังนั้นให้ใช้กับสิ่งที่อยู่ในใจ
สร้างไดเรกทอรีและชื่อไฟล์ด้วยการขึ้นบรรทัดใหม่
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
แสดงอย่างถูกต้อง:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
แต่wc
จะนับไดเรกทอรีและไฟล์ที่มีบรรทัดใหม่เป็น 2 รายการไม่ใช่หนึ่งรายการ
$ ls -1 | wc -l
10
วิธีหนึ่งในการหลีกเลี่ยงปัญหานี้หากใช้การนำ GNU ไปใช้find
คือใช้find
ความสามารถในการพิมพ์อย่างอื่นแทนไฟล์แต่ละไฟล์ที่พบแล้วนับจำนวนนั้นแทน
$ find . -printf . | wc -c
9
นี่เรากำลังค้นหาทุกอย่างในไดเรกทอรีปัจจุบัน (ยกเว้น..
) และพิมพ์จุด ( .
) สำหรับแต่ละและจากนั้นนับจุดโดยใช้ความสามารถที่จะนับไบต์แทนสาย,wc
wc -c
/usr/bin
ทุกรูปแบบจะมีรูปแบบที่ดี (และยังไม่มีช่องว่างดังนั้นในทางเทคนิคคุณสามารถทำได้echo * | wc -w
) มันก็คุ้มค่าที่จะสังเกตว่าสิ่งเหล่านี้ทั้งหมดจะแตกในชื่อไฟล์ที่มีการขึ้นบรรทัดใหม่
ls -l
หรือls -1
จะทำลาย b / c เรากำลังนับบรรทัดไม่ใช่คำพูด! find
อาจแบ่งอีกครั้ง แต่เรานับเส้นไม่ได้คำ
touch $'foo\nbar'
ภายในไดเรกทอรีว่างแล้วตามด้วยหนึ่งในคำสั่งของคุณ (พูดls -1 | wc -l
) จะรายงานสองไฟล์มากกว่าหนึ่ง - เพราะไฟล์นั้นมีสองบรรทัดเท่าที่wc
เกี่ยวข้อง ยกเว้นการขึ้นls
บรรทัดใหม่ด้วยอักขระอื่น (ฉันไม่คิดว่ามันจะเป็นเช่นนั้น แต่อีกครั้งฉันไม่สามารถทดสอบได้ในตอนนี้)
wc -c
ปัญหาเมื่อนับจำนวนงวดหรือไม่
หากคุณต้องการทำลายจำนวนไฟล์แต่ละประเภทซ้ำ ๆ ภายใต้ dir บางอันด้วย GNU find
คุณสามารถทำได้:
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
เปิด/usr/bin
ในระบบของฉันซึ่งให้:
3727 regular files
710 symbolic links
เปิด/dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
สำหรับ symlink หากคุณต้องการนับเป็นประเภทของไฟล์ที่ชี้ไปมากกว่าsymbolic links
คุณสามารถเปลี่ยนเป็น:
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
ซึ่งตอนนี้ให้สำหรับฉัน/usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(symlink ที่ใช้งานไม่ได้คือ symlink ไปยังไฟล์ซึ่งfind
ไม่สามารถระบุประเภทได้เนื่องจากไฟล์ไม่มีอยู่หรืออยู่ในไดเรกทอรีที่คุณไม่สามารถเข้าถึงหรือมีลูปในการแก้ไขเส้นทางของไฟล์ ในกรณีของฉันทั้งสองที่ symlink ไปยังไฟล์ที่หายไป)
ไม่นับผู้ที่และ.
..
หากคุณต้องการให้พวกเขารวม (ทำไมคุณจะ?) ไม่มีวิธีอื่นที่มีfind
กว่าสมมติว่าพวกเขามีสำหรับทุกไดเรกทอรีและนับพวกเขาอย่างเป็นระบบ:
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
ซึ่งให้กับฉันแล้ว/usr/bin
:
2 directories
3727 regular files
710 symbolic links
หากคุณไม่สามารถเข้าถึง GNU find
คุณสามารถเขียนใหม่เป็น:
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
ตอนนี้อย่างเคร่งครัดพูดเราไม่ได้รับการนับไฟล์แต่รายการไดเรกทอรี ไดเรกทอรีเช่น/usr/bin
โดยทั่วไปมีหลายรายการที่ชี้ไปที่ไฟล์เดียวกัน ตัวอย่างเช่นที่นี่ฉันมี:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
รายการเหล่านี้คือ 3 รายการไดเรกทอรี (ชื่อไฟล์หรือที่รู้จักกันว่าฮาร์ดลิงก์) ไปยังไฟล์เดียวกัน (รายการที่มี inode 672252 หากต้องการนับไฟล์แทนรายการไดเรกทอรีและด้วย GNU find
และ GNU uniq
(ไม่สนใจ.
และ..
ไฟล์ซึ่งเป็นลิงก์ไปยังไดเรกทอรีอื่น ๆ ):
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
บนของฉัน/usr/bin
ที่ให้:
3711 regular files
710 symbolic links
คุณไม่ได้พูดว่าถ้าคุณต้องการไฟล์ทั้งหมดภายใต้ / usr / bin ซ้ำหรือเพียงแค่อยู่ในระดับแรก นอกจากนี้คุณจะได้คำที่คุณนับได้อย่างไร วิธีปกติในการค้นหาคือใช้ find ใน wc ดังนี้: find / usr / bin | wc -l ค้นหาจะแสดงรายการทุกสิ่งที่นั่นไดเรกทอรีและไฟล์ Wc -l จะนับบรรทัดทั้งหมดใน find output นี่คือการมอบหมายชั้นเรียนหรือไม่? มันก็โอเคถ้าเป็น แต่ฉันสงสัยว่าทำไมคุณถึงต้องการข้อมูลนี้เพื่อที่ฉันจะได้ปรับการตอบสนองให้ดีขึ้น โปรดแจ้งให้เราทราบหากคุณต้องการเพิ่มเติม คอสตา
ในทุบตีโดยไม่ต้องใช้เครื่องมือภายนอก
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
ในทุบตีโดยไม่ต้องใช้เครื่องมือภายนอกและการเรียกซ้ำ
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.
หรือ..
รายการ คุณอาจต้องการแปลงไฟล์เป็นไฟล์ปกติ