Làm cách nào tôi có thể sử dụng word counter ( wc
) và piping để đếm xem có bao nhiêu tệp hoặc thư mục trong /usr/bin
thư mục?
Làm cách nào tôi có thể sử dụng word counter ( wc
) và piping để đếm xem có bao nhiêu tệp hoặc thư mục trong /usr/bin
thư mục?
Câu trả lời:
Một cách tiếp cận là sử dụng ls
để cung cấp cho chúng tôi danh sách các tệp, nhưng chúng tôi muốn danh sách này được đảm bảo chỉ hiển thị 1 tệp hoặc thư mục trên mỗi dòng. Công -1
tắc sẽ làm điều này cho chúng tôi.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Tạo dữ liệu mẫu ở trên trong một thư mục trống.
$ mkdir dir{1..3}
$ touch file{A..C}
Kiểm tra nó:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Bây giờ để đếm, bạn có thể sử dụng wc -l
để đếm số lượng dòng, tương ứng với một tệp hoặc thư mục trong ls -1
đầu ra.
$ ls -1 | wc -l
6
(lưu ý tuy nhiên nó không bao gồm các tệp ẩn)
Để đếm một trong hai tệp hoặc thư mục, bạn cần thay đổi chiến thuật của mình một chút. Trong trường hợp này tôi sẽ sử dụng ls -l
vì nó hiển thị thư mục và tập tin aa là gì.
$ 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
Sau đó, chúng ta có thể sử dụng grep
để lọc ra các thư mục hoặc không phải thư mục như vậy:
# 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
Bây giờ chỉ cần sử dụng wc -l
một lần nữa để đếm ở trên:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Mặc dù vậy, bạn có thể tránh wc
hoàn toàn, và sử dụng grep
's -c
lựa chọn:
$ ls -l | grep -c '^d'
(một lần nữa, các tệp ẩn không được bao gồm. Lưu ý rằng thư mục và thông thường là hai loại tệp. Có nhiều loại giống như ống được đặt tên, liên kết tượng trưng, thiết bị, ổ cắm ...).
Nếu bạn cần tìm các tệp và thư mục theo cách đệ quy /usr/bin
thì bạn có thể muốn thay đổi hoàn toàn các chiến thuật và sử dụng một công cụ khác được gọi find
.
$ find /usr/bin | wc -l
4632
(mặc dù ở trên /usr/bin
chính nó được bao gồm trong số)
Các kỹ thuật tương tự tôi đã sử dụng ở trên có thể được sử dụng ls
để làm một cái gì đó tương tự nhưng ls
nhìn chung không phải là một công cụ tốt để phân tích đầu ra. find
mặt khác được xây dựng cho việc này và cung cấp các công tắc để tìm tệp hoặc thư mục.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(lưu ý rằng lần này, find
bao gồm các tệp ẩn (ngoại trừ .
và ..
)).
Tôi chưa bao giờ hiểu tại sao một ký tự dòng mới là một ký tự hợp pháp để sử dụng khi tạo tên tệp hoặc tên thư mục. Vì vậy, các phương pháp được thảo luận ở trên bằng cách sử dụng wc
và ls
sẽ không tranh cãi với chúng, vì vậy hãy sử dụng chúng với ý nghĩ đó.
Tạo một thư mục và tên tập tin với dòng mới.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
cho họ thấy chính xác:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Nhưng wc
tính các thư mục và tệp chứa dòng mới là 2 mục chứ không phải một.
$ ls -1 | wc -l
10
Một phương pháp để giải quyết vấn đề này, nếu sử dụng triển khai GNU find
là sử dụng find
khả năng của một bản in khác thay cho mỗi tệp mà nó tìm thấy và sau đó đếm chúng.
$ find . -printf . | wc -c
9
Ở đây chúng tôi tìm thấy mọi thứ trong thư mục hiện tại (ngoại trừ ..
) và in một dấu chấm ( .
) cho mỗi dấu chấm , sau đó đếm các dấu chấm bằng cách sử dụng wc
khả năng đếm byte thay vì các dòng , wc -c
.
/usr/bin
tất cả sẽ được định dạng tốt (và cũng sẽ không chứa khoảng trắng, vì vậy về mặt kỹ thuật bạn thậm chí có thể chỉ echo * | wc -w
), đáng chú ý là tất cả những thứ này sẽ phá vỡ tên tập tin có chứa dòng mới.
ls -l
hoặc ls -1
sẽ phá vỡ b / c chúng tôi đang đếm dòng, không phải từ! Có find
thể phá vỡ, nhưng một lần nữa, chúng ta đang đếm các dòng không phải là từ.
touch $'foo\nbar'
trong một thư mục trống được theo sau bởi một trong các lệnh của bạn (giả sử ls -1 | wc -l
) sẽ báo cáo hai tệp chứ không phải một - vì một tệp đó là hai dòng theo như wc
có liên quan. Trừ khi ls
thay thế các dòng mới bằng một số nhân vật khác (tôi không nghĩ vậy, nhưng một lần nữa tôi không ở vị trí để kiểm tra ngay bây giờ).
wc -c
một vấn đề khi đếm thời gian?
Nếu bạn muốn phân tích số lượng từng loại tệp theo đệ quy theo một số thư mục, với GNU find
, bạn có thể làm:
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 (&)/'
Trên /usr/bin
hệ thống của tôi, điều đó mang lại:
3727 regular files
710 symbolic links
Vào /dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Đối với liên kết tượng trưng, nếu bạn muốn tính chúng là loại tệp mà chúng trỏ đến chứ không phải symbolic links
, bạn có thể thay đổi nó thành:
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 (&)/'
Mà bây giờ cho tôi /usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(một liên kết tượng trưng bị hỏng là một liên kết tượng trưng đến một tệp find
không thể xác định loại vì tệp không tồn tại hoặc nằm trong thư mục mà bạn không có quyền truy cập hoặc có một vòng lặp trong độ phân giải đường dẫn của tệp Trong trường hợp của tôi, đó là 2 nơi liên kết tượng trưng đến các tệp đã biến mất).
Không ai trong số đó .
và ..
. Nếu bạn muốn bao gồm chúng (tại sao bạn lại như vậy?), Không có cách nào khác find
ngoài việc cho rằng chúng ở đó cho mọi thư mục và đếm chúng một cách có hệ thống:
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 (&)/'
Mà sau đó cho tôi /usr/bin
:
2 directories
3727 regular files
710 symbolic links
Nếu bạn không có quyền truy cập vào GNU find
, bạn có thể viết lại cái đầu tiên dưới dạng:
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
Bây giờ, nói đúng ra, chúng tôi đã không đếm các tập tin mà là các mục trong thư mục . Một thư mục như /usr/bin
thường có một vài mục trỏ đến cùng một tệp. Chẳng hạn, ở đây, tôi có:
$ 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
Đó là 3 mục nhập thư mục (còn gọi là tên tệp hay liên kết cứng) vào cùng một tệp (tệp có inode 672252. Để đếm tệp thay vì mục nhập thư mục và với GNU find
và GNU uniq
(bỏ qua .
và ..
các tệp dù sao cũng là liên kết cứng đến các thư mục khác):
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 (&)/'
Theo tôi /usr/bin
, điều đó mang lại:
3711 regular files
710 symbolic links
Bạn chưa nói nếu bạn muốn tất cả các tệp dưới / usr / bin đệ quy hoặc chỉ dưới cấp độ đầu tiên. Ngoài ra, làm thế nào bạn sẽ có được những từ mà bạn đang đếm? Cách thông thường để tìm hiểu là chạy tìm vào wc. Như thế này: find / usr / bin | wc -l Find sẽ liệt kê mọi thứ ở đó, thư mục và tập tin. Wc -l sẽ đếm tất cả các dòng trong đầu ra tìm. Đây có phải là một bài tập lớp? Sẽ ổn nếu có nhưng tôi đã tự hỏi tại sao bạn cần thông tin này để tôi có thể điều chỉnh phản hồi cẩn thận hơn. Xin vui lòng cho tôi biết nếu bạn cần thêm. Costa
Trong bash, không có công cụ bên ngoài.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
Trong bash, không có công cụ bên ngoài và đệ quy.
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
.
cả ..
các mục nhập. Bạn có thể muốn phân biệt tệp so với tệp thông thường.