Thư mục ./ và ../ là gì?


20

Câu hỏi đơn giản, nhưng tôi không chắc chắn nơi để tìm và google không trả lời các dấu chấm và dấu gạch chéo.

Tôi chỉ đang cố gắng đếm # tệp và thư mục trong thư mục hiện tại (không bao gồm các thư mục con / tệp) và đang cố phân biệt ls -1 | wc -lls | wc -lvì chúng có vẻ giống hệt nhau. Một trang web tôi đang xem cho biết "Hãy nhớ rằng đây cũng đang đếm các thư mục ./ và ../." liên quan đến cái có ls -1, và tôi không chắc điều đó có nghĩa là nó bao gồm các thư mục trước đó hay thứ gì đó (mà tôi không muốn), nhưng dường như nó không làm điều đó từ thử nghiệm.

Ai đó có thể xác nhận một trong những tệp nào là đủ để đếm # tệp và thư mục trong thư mục hiện tại không (không phụ) và ý nghĩa của các thư mục ./ và ../?


"Hãy nhớ rằng điều này cũng đang đếm các thư mục ./ và ../" là sai (trừ khi đó là một lỗi đánh máy cho "." Và "..".
vonbrand

Câu trả lời:


15

Mỗi thư mục trên một hệ thống Unix (và có lẽ mọi hệ thống khác cũng vậy) chứa ít nhất hai mục nhập thư mục. Đó là .(thư mục hiện tại) và ..(thư mục mẹ). Trong trường hợp thư mục gốc, các điểm này đến cùng một vị trí, nhưng với bất kỳ thư mục nào khác, chúng đều khác nhau. Bạn có thể thấy điều này cho chính mình bằng cách sử dụng stat, pwdcdcác lệnh (trên Linux):

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$

Lưu ý rằng binsbinmỗi có hai liên kết đến nó. Một là mục nhập thư mục trong thư mục gốc, và cái còn lại là .mục bên trong thư mục đó.

Sử dụng lsvới một đường ống wc -llà một mẹo đơn giản để đếm số lượng dòng trong đầu ra của ls. Giả định là mỗi tệp hoặc thư mục sẽ chiếm chính xác một dòng trong đầu ra. GNU ls sẽ, khi đầu ra là một thiết bị đầu cuối, sẽ tự động làm điều này; những người khác có thể cần -1tùy chọn để bật hành vi một cách rõ ràng. wc -lchỉ cần đếm và xuất số lượng dòng ( -l) trong đầu vào của nó.

Vấn đề với cách tiếp cận đó là trong Linux và trên các hệ thống tệp thường được sử dụng trên Linux, tên tệp và thư mục (chúng thực sự là một và giống nhau về vấn đề này) được phép chứa các ký tự dòng mới . Với sự hiện diện của những cái đó, một trong hai phương thức sẽ bị tách ra - những mục đó sẽ được tính là hai hoặc nhiều mục khi trong thực tế chúng là một.

Miễn là bạn đang sử dụng GNU ls, không có mục nhập thư mục có tên chứa ký tự dòng mới và không có bí danh lẻ cho ls(ví dụ ls -a:), cả hai sẽ xuất số lượng tệp và thư mục trong thư mục hiện tại (hoặc được chỉ định). Đối với hầu hết mọi người, điều này là đủ tốt, nhưng nó không hợp lệ trong trường hợp chung .

Nếu bạn cần xử lý các ký tự bất thường (chủ yếu là dòng mới) trong tên mục nhập thư mục, tôi khuyên bạn nên sử dụng -btùy chọn ls để thoát chúng. ls -1bAsẽ in mỗi tên mục nhập thư mục trên dòng riêng của nó, thoát các ký tự bất thường (vì vậy mỗi mục nhập thư mục sẽ được xem là một), bao gồm mọi dấu chấm và -directories. Xử wc -llý một dòng lệnh hoàn chỉnh ls -1bA | wc -lsẽ báo cáo số lượng tệp và thư mục trong thư mục hiện tại (nhưng bỏ qua ...đó là sự khác biệt giữa -a-A), nhưng không đi vào bất kỳ thư mục con nào. Nếu bạn không muốn bất kỳ dấu chấm nào được tính vào tổng số, chỉ cần bỏ qua -Atham số ls.


Cả hai -a-Abao gồm các tệp ẩn cũng như tôi đã nhận ra tôi muốn tránh, vì vậy nhiều nhất tôi sẽ làm ls -b | wc -l, nhưng điều này cho tôi câu trả lời đúng. Là dòng tôi sao chép và dán liên quan đến lệnh này không chính xác? Nếu đúng, tôi không nên nhận đầu ra là 8 khi có 6 tệp hoặc thư mục trong một thư mục?
Adam

@Adam vâng, điều đó có thể sẽ tạo ra mánh khóe ("ls -b | wc -l"); bạn cũng có thể sử dụng "-1" (dấu gạch ngang + số một) để buộc một danh sách trong một cột thay vì tất cả trên một dòng, nhưng điều đó vẫn xảy ra khi chuyển sang lệnh khác. Vì vậy (imho) Tôi sẽ để nó là "ls -1b | wc -l"; và để "kiểm tra", chạy "ls -1b" và đếm số dòng, sau đó chạy "ls -1b | wc -l" và xác minh kết quả. (Đó là cách gỡ lỗi / kiểm tra đường ống.)
michael

@Sardathrion, Câu hỏi thường gặp đó khá sai lệch. Các quy ước hệ thống tập tin Unix không "lạ"; nơi chúng phổ biến, đó là hệ thống khác chọn chúng. Nhưng OK. Sau đó, nó nói rằng "lệnh tập tin sử dụng số ma thuật để xác định ...", điều này là sai: Nó cũng sử dụng rất nhiều phương pháp phỏng đoán. Không đáng tin cậy trong cuốn sách của tôi.
vonbrand

@vonbrand: đủ công bằng, xóa link. Tôi chỉ lướt qua nó và nó có vẻ tốt. Tôi biết tôi đã tìm thấy một thứ tốt nhưng bây giờ không thể nhớ nó ở đâu.
Sardathrion - Phục hồi Monica

1
Bạn đang nhầm lẫn :. và .. là những đồ tạo tác lịch sử từ UNIX vào những năm 1970 và là kết quả của thời điểm chưa có mkdir()cuộc gọi hệ thống nào. Không phải tất cả các hệ thống tập tin đều có chúng và thậm chí chúng không cần thiết cũng không được POSIX yêu cầu.
schily

6

Để trả lời câu hỏi trong chủ đề:

Khi một thư mục B được tạo trong Unix, nó được thêm dưới dạng một mục mới vào thư mục A khác (thư mục mẹ của nó) và trong B, hai mục được thêm vào: một được gọi .là liên kết cứng với chính nó và một mục được gọi ..là cứng liên kết đến A.

Đó là những liên kết cứng duy nhất đến các thư mục được phép (mặc dù một số phiên bản cũ hơn của một số Unice cũng cho phép các liên kết tùy ý).

đó là lý do tại sao với hầu hết các hệ thống tệp ( btrfslà một ngoại lệ đáng chú ý), số lượng linksthư mục là một dấu hiệu cho biết có bao nhiêu thư mục con (chiếm các ..mục nhập của chúng ).

Khi bạn đổi tên / di chuyển một thư mục, nếu nó vào cùng một thư mục (dưới một tên khác), chỉ có mục nhập tên Ađược thay đổi. B ...không bị ảnh hưởng. Nhưng nếu bạn di chuyển nó làm một thư mục khác nhau, sau đó ..trong Bsẽ thay đổi. Điều đó giải thích tại sao bạn có thể đổi tên một thư mục mà bạn không có quyền truy cập ghi (giả sử bạn có quyền truy cập ghi vào thư mục mẹ) chỉ khi bạn không chuyển nó sang thư mục khác (nếu không, việc thay đổi ..mục nhập sẽ ngăn chặn bạn khỏi di chuyển nó).

Coi chừng: /a/b/../ccó thể không giống như /a/c/a/bcó thể là một liên kết tượng trưng đến một số thư mục khác.

Một ngoại lệ đó là khi đường dẫn đó được trao cho cdlệnh tới một số shell. Những người cdđối xử .. hợp lý bỏ qua các ..mục trong thư mục. Một lý do tại sao bạn thường thấy cd -Ptrong các tập lệnh được viết đúng, để vô hiệu hóa tính năng đó có thể gây nhầm lẫn và không nhất quán.

Để đếm số lượng mục trong thư mục hiện tại không bao gồm ...với bash, bạn có thể làm:

shopt -s nullglob dotglob
set -- *
echo "$#"

Với zsh:

f=(*(ND))
echo $#f

Di chuyển

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

Tôi có chút bối rối; tất cả ba trong số những người bạn liệt kê thêm một vào số lượng thực tế. ví dụ: nếu tôi có 6 tệp hoặc thư mục trong một thư mục, chúng xuất 7, không phải 6. Đối với tôi, có vẻ như ls | wc -llà tệp duy nhất loại trừ ...
Adam

1
@Adam, lskhông liệt kê các tập tin ẩn. Bạn cần ls -Aphải có được như những người. NẾU bạn không muốn đếm các tập tin ẩn, hãy tắt dotglob(cho bash) hoặc D(cho zsh) hoặc thêm ! -name '.*'trước -printcho find.
Stéphane Chazelas

Vâng, tôi chỉ nhận thấy điều này sau khi thực sự liệt kê các tập tin. Bạn có biết tại sao ls | wc -lvẫn cho tôi câu trả lời đúng và loại trừ các tệp ẩn, .& ..?
Adam

1
Adam, trong thư mục của bạn, bạn có ., ..và tập tin khác mà bắt đầu tên bằng .mà không được liệt kê bởi ls nhưng sẽ bằng ls -A. Vì vậy, ls | wc -lkhông cung cấp cho bạn câu trả lời chính xác bởi vì nó không tính tập tin ẩn đó.
Stéphane Chazelas

1
Có, ...là các tập tin ẩn kể từ khi chúng bắt đầu bằng một .. Thậm chí còn có một truyền thuyết giải thích rằng các dotfiles bị ẩn do vô tình vì việc triển khai sớm lschỉ nhằm loại trừ ..., nhưng có một lỗi khiến nó loại trừ bất kỳ tệp nào bắt đầu .. ls | wc -lkhông hoạt động nếu tên tệp chứa các ký tự dòng mới.
Stéphane Chazelas

1

Tôi không phải là một chuyên gia Linux tuyệt vời, nhưng tôi biết Linux (đã từng là quản trị viên 16 năm trước, trên Slackware :) thời xưa rất tốt

các thư mục ./ và ../ thật đơn giản :. là thư mục hiện tại, .. là thư mục trước đó (trong cây của lệnh thư mục pwd -local-

Nếu nó đếm chúng, tôi nghĩ họ thêm 2 vào tổng số danh sách, không thực sự đi theo đệ quy và đếm thư mục bên dưới thư mục hiện tại, và cũng đếm lại thư mục hiện tại (.) :))

Vì vậy, về cơ bản tôi nghĩ rằng nó thêm giá trị 2 vào số đã đếm (tệp) trong thư mục hiện tại.

Bất cứ ai sửa tôi nếu tôi sai.

Tôi chỉ đăng bài để giúp đỡ và thấy rằng không ai trả lời câu hỏi này ở đây, họ có thể đang bận. Nhưng chỉ cần thử nghiệm và xem nếu bạn có 10 tệp và nhận được 12 tệp thì đó là nó.


Vâng, Adrian là chính xác :. là thư mục hiện tại và .. là thư mục ngay trên phân cấp.
schaiba

.. không phải lúc nào cũng đề cập đến thư mục trước đó trong cây: in "/" .. cũng đề cập đến thư mục hiện tại.
Bonsi Scott

bởi vì bạn có thể ở / root hệ thống tập tin?
Adrian Tanase

Nếu nó thêm hai vào # tệp trong một thư mục thì tại sao tôi lại nhận được câu trả lời đúng khi kiểm tra nó trong thiết bị đầu cuối trên osx? ví dụ: một thư mục có 6 tệp hoặc thư mục sẽ xuất 6, không phải 8 khi tôi thực hiệnls | wc -1
Adam

Tôi nhận ra rằng đó là vì chúng bao gồm các tệp ẩn (cụ thể là .ds_store), nhưng tôi vẫn không thấy cách ls | wc -lbao gồm ...khi tôi nhận được câu trả lời đúng, trái ngược với câu trả lời đúng + 2.
Adam
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.