Câu trả lời:
Đây là một cách tiếp cận hoàn toàn khác nhau dựa trên GNU find
và uniq
. Điều này nhanh hơn và thân thiện với CPU hơn nhiều so với các câu trả lời dựa trên việc thực hiện lệnh shell đếm các tệp cho mỗi thư mục được tìm thấy.
find . -type f -printf '%h\n' | sort | uniq -d
Các find
lệnh in thư mục của tất cả các file trong hệ thống phân cấp và uniq
chỉ hiển thị các thư mục xuất hiện ít nhất hai lần.
-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
find . -type d \
-exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
-print
Điều này sẽ tìm thấy tất cả các tên trong hoặc dưới thư mục hiện tại và sau đó lọc ra tất cả các tên không phải là tên của thư mục.
Các tên thư mục còn lại sẽ được đặt cho tập lệnh ngắn này:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Kịch bản lệnh này sẽ đếm số lượng tệp thông thường (bỏ qua các liên kết tượng trưng) trong thư mục được cung cấp làm đối số dòng lệnh đầu tiên (từ find
). Lệnh cuối cùng trong tập lệnh là một bài kiểm tra để xem liệu số đếm là 2 hay lớn hơn. Kết quả của bài kiểm tra này là giá trị trả về (trạng thái thoát) của tập lệnh.
Nếu thử nghiệm thành công, -print
sẽ gây ra find
việc in đường dẫn đến thư mục.
Để xem xét các tệp bị ẩn (các tệp có tên bắt đầu bằng dấu chấm), hãy thay đổi sh -c
tập lệnh từ nói
for n in "$1"/*; do
đến
for n in "$1"/* "$1"/.*; do
Kiểm tra:
$ tree
.
`-- test
|-- a
|-- dir1
| |-- a
| |-- b
| `-- c
`-- dir2
|-- dira
|-- dirb
| |-- file-1
| `-- file-2
`-- dirc
6 directories, 6 files
$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb
[ "" -ge 2 ]
là một bài kiểm tra hợp lệ.
dash
, bash --posix
Và test
tất cả hiển thị một thông báo lỗi và thoát ra với 2 (tức là "lỗi Đã xảy ra")
ksh
đang chạy sh
. Sẽ sửa đổi ngay lập tức. Cảm ơn đã chọc tôi! :-)
[ -f ... ]
các liên kết tượng trưng liên kết. Bạn nên thêm một bài kiểm tra để loại bỏ chúng vì câu hỏi chỉ định rằng chỉ nên tính các tệp thông thường.
Với sự giúp đỡ của câu trả lời của Gilles về SU và ngược lại và một số sửa đổi, đây là những gì bạn cần.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Cây thư mục.
.
├── test
│ ├── dir1
│ │ ├── a
│ │ ├── b
│ │ └── c
│ ├── dir2
│ │ ├── dira
│ │ │ └── a file\012with\012multiple\012line
│ │ ├── dirb
│ │ │ ├── file-1
│ │ │ └── file-2
│ │ └── dirc
│ ├── diraa
│ ├── dirbb
│ ├── dircc
│ └── x
│ └── x1
│ └── x2
└── test2
├── dir3
└── dir4
Kết quả:
./test
./test/dir1
./test/dir2/dirb
test
và các dir2
thư mục trong thiết lập thử nghiệm của tôi (xem câu trả lời của tôi).
test/x1
và test/x2
dưới dạng tệp ... $1
và $2
sẽ là thư mục cho test
, và thư mục sẽ bị bỏ qua.
Cách tiếp cận find
+ khác wc
:
find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print
path/currdir
- đường dẫn đến thư mục hiện tại của bạn
-maxdepth 1
- chỉ xem xét các thư mục con trực tiếp
! -empty
- bỏ qua các thư mục con trống
! -path "path/currdir"
- bỏ qua đường dẫn thư mục hiện tại
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
được gán với số lượng tệp cho mỗi thư mục con tìm thấy
[ $count -ge 2 ] ... -print
- in tên / đường dẫn thư mục con chứa 2 hoặc nhiều tệp thông thường
find
. Trong trường hợp này, vì GNUfind
sẽ đọc tên của các thư mục có các ký tự không thể in được trong miền địa phương hiện tại (như "ä" trong miền địa phương C). Xem thêm unix.stackexchange.com/questions/321697/iêu