Làm thế nào để chỉ hiển thị các tập tin ẩn trong Terminal?


154

Tôi có một thư mục chứa hàng ngàn tệp, một số trong số chúng bị ẩn.

Lệnh ls -aliệt kê tất cả các tệp, bao gồm cả các tệp bị ẩn, nhưng tôi chỉ cần liệt kê các tệp bị ẩn.

Tôi nên sử dụng lệnh nào?


1
ls -ld .*ls -ald .*
Đơn

Câu trả lời:


189

Lệnh :

ls -ld .?* 

Sẽ chỉ liệt kê các tập tin ẩn.

Giải thích:

 -l     use a long listing format

 -d, --directory
              list  directory entries instead of contents, and do not derefer‐
              ence symbolic links

.?* will only state hidden files 

8
Bạn không cần hai dấu hỏi trong đó, * bao trùm nó (? Chỉ khớp với bất kỳ ký tự đơn nào, * khớp với bất kỳ số nào trong số chúng).
psusi

13
@psusi, tôi nghĩ mục đích là loại trừ ...ra khỏi trận đấu. Tuy nhiên, nó cũng sẽ loại trừ các tên tập tin ẩn một ký tự (hoàn toàn hợp pháp) .a, .1v.v. Có lẽ một quả cầu được mở rộng tốt hơn sẽ có .!(|.)nghĩa là dấu chấm theo nghĩa đen được theo sau bởi bất cứ thứ gì ngoại trừ không có gì hoặc một dấu chấm (đơn) khác tức làls -d .!(|.)
Steeldo

@steel ấn, gọn gàng, ?? phiên bản không loại trừ "." và "..". Đây dường như là kết quả của một trò hề thú vị: không? cũng không * sẽ khớp với một dấu chấm, nhưng dấu? phải phù hợp với một cái gì đó nếu không tên được bỏ qua.
psusi

Để xác định thư mục và tệp, hãy thêm tùy chọn F, tức là tên thư mục ls -ldF.? * Có "/" như các tệp ký tự được hiển thị lần cuối không.
RCF

1
Điều này gần như hoạt động ngoại trừ nó cũng liệt kê thư mục ẩn như .vim, mà tôi coi là không phải là một tập tin ở đây. Tôi sửa đổi nó một chút như ls -ldp.? * | grep -v / Đây chỉ liệt kê các tập tin ẩn không bị ẩn thư mục
Fred Yang

31
ls -d .!(|.)

Liệu chính xác những gì OP đang tìm kiếm.


1
Làm thế nào mà làm việc?
SarcasticSully

danh sách thư mục bất cứ điều gì với a. và không liệt kê bất cứ thứ gì mà không có ai là những gì nó được dịch ra.
patrick

1
Tôi hiểu rằng trong !(pattern-list), pattern-listlà một danh sách một hoặc nhiều mẫu được phân tách bằng một |, nhưng điều khó hiểu đối với tôi là bạn không có bất kỳ mẫu nào ở bên trái |. Bạn có thể vui lòng giải thích cú pháp đó cho tôi?
Carlos Mendoza

2
@CarlosMendoza sẽ trở thành mô hình trống rỗng, vì vậy điều này giống như .không được theo sau (không có gì hoặc .), ngoại trừ .chính nó và ...
muru

16

Nếu bạn chỉ muốn các tệp trong thư mục hiện tại của bạn (không có đệ quy), bạn có thể làm

echo .[^.]*

Điều đó sẽ in tên của tất cả các tệp có tên bắt đầu bằng a .và được theo sau bởi một hoặc nhiều ký tự không dấu chấm. Lưu ý rằng điều này sẽ thất bại đối với các tệp có tên bắt đầu bằng các dấu chấm liên tiếp, vì vậy, ví dụ ....foosẽ không được hiển thị.

Bạn cũng có thể sử dụng find:

find -mindepth 1 -prune -name '.*'

Việc -mindepthđảm bảo chúng tôi không khớp .-prunephương tiện findsẽ không rơi vào các thư mục con.



4

Sử dụng findawk,

find . -type f | awk -F"/" '$NF ~ /^\..*$/ {print $NF}'

Giải trình:

find . -type f -> Liệt kê tất cả các tệp trong thư mục hiện tại cùng với đường dẫn như,

./foo.html
./bar.html
./.foo1

awk -F"/" '$NF ~ /^\..*$/ {print $NF}'

/khi phân tách trường awk kiểm tra trường cuối cùng có nhìn thấy dấu chấm hay không. Nếu nó bắt đầu bằng một dấu chấm, thì nó sẽ in trường cuối cùng của dòng tương ứng đó.


Bạn chỉ có thể sử dụng find -type f. Bạn không cần phải thiết lập đường dẫn tìm kiếm hay -name "*".
terdon

3

find thường là một lựa chọn tốt hơn cho các tìm kiếm phức tạp hơn là sử dụng tên toàn cầu.

find . -mindepth 1 -maxdepth 1 -name '.*'

hoặc là

find . -mindepth 1 -maxdepth 1 -name '.*' -o -name '*~'

find . tìm kiếm thư mục hiện tại

-mindepth 1không bao gồm và .. từ danh sách

-maxdepth 1 giới hạn tìm kiếm trong thư mục hiện tại

-name '.*' tìm tên tập tin bắt đầu bằng dấu chấm

-o hoặc là

-name '*~' tìm tên tệp kết thúc bằng dấu ngã (thông thường, đây là các tệp sao lưu từ các chương trình chỉnh sửa văn bản)

Tuy nhiên, điều này và tất cả các câu trả lời khác bỏ lỡ các tệp trong .hiddentệp của thư mục hiện tại . Nếu bạn đang viết một tập lệnh, thì những dòng này sẽ đọc .hiddentệp và hiển thị tên tệp của những tập lệnh tồn tại.

if [[ -f .hidden]] # if '.hidden' exists and is a file
then
    while read filename # read file name from line
    do
        if [[ -e "$filename" ]] # if the read file name exists
        then
            echo "$filename" # print it
        fi
    done < .hidden # read from .hidden file
fi

Là gì .hiddentập tin? Tại sao sẽ có một tệp được gọi .hiddencó chứa tên tệp? Dù sao, nếu có một lý do tại sao bạn sẽ làm một cái gì đó phức tạp khi tất cả những gì bạn cần sẽ là cat .hidden? findLệnh của bạn là chính xác (ish) nhưng -name '*~'không liên quan. Các tệp kết thúc bằng dấu ngã là các tệp sao lưu nhưng không bị ẩn theo bất kỳ cách nào.
terdon

@terdon .hiddenTệp này dành cho các tệp và thư mục bạn muốn ẩn khi bạn không thể thay đổi tên tệp / thư mục để bắt đầu bằng dấu chấm. Đối với các tệp kết thúc bằng dấu ngã, nó phụ thuộc vào hệ thống. ls -Bsẽ bỏ qua các tệp như vậy, như hầu hết các nhà thám hiểm tệp GUI.
Đánh dấu H

cat .hiddencó thể hiển thị các tệp không còn tồn tại nếu các tệp đó bị xóa hoặc di chuyển kể từ khi được thêm vào .hiddentệp.
Đánh dấu H

Điều này hoạt động tốt.
Penghe Geng

2

Tôi nghĩ rằng bạn có thể làm điều đó với lệnh sau.

ls -a | grep "^\." | grep -v "^\.$" | grep -v "^\..$"

ls -a lệnh bạn đã nhập, hiển thị tất cả các tệp và thư mục trong thư mục làm việc hiện tại.

grep "^\."lệnh tôi đã nối, bộ lọc đầu ra chỉ hiển thị các tệp bị ẩn (Tên bắt đầu bằng ".").

grep -v "^\.$" | grep -v "^\..$" lệnh tôi đã nối, bộ lọc đầu ra để loại trừ., .. (Chúng là thư mục hiện tại và thư mục mẹ).

Nếu một số tên tệp có thể có nhiều dòng "\n", ví dụ trên có thể không chính xác.

Vì vậy, tôi đề nghị lệnh sau để giải quyết vấn đề.

find -maxdepth 1 -name ".[!.]*"


@ RaduRădeanu Tôi thấy nhận xét của bạn, Thật tốt quá. Tôi chỉnh sửa câu trả lời của tôi một lần nữa. Cảm ơn bạn đã bình luận của bạn.
xiaodongjie

2

Những gì bạn có thể đã làm, is ls .?*Hoặc ls .!(|)điều đó sẽ cho bạn thấy tất cả mọi thứ trong tập tin / thư mục ẩn hiện tại trên đầu trang và các tập tin / thư mục khác bên dưới

ví dụ: từ thiết bị đầu cuối của tôi

$ ls .?*       
.bash_history    .dmrc        .macromedia   .weather
.bash_logout     .gksu.lock   .profile      .wgetrc
.bash_profile    .bashrc.save .ICEauthority .toprc           .Xauthority
.bashrc          .lastdir     .viminfo      .xsession-errors
.bashrc~         .dircolors   .lynxrc       .vimrc           .xsession-errors.old

..:
Baron

.adobe:
Flash_Player

.aptitude:
cache  config

.cache:
compizconfig-1                              rhythmbox
dconf                                       shotwell

Bây giờ chú ý trong các kết quả ở trên, nó hiển thị cho bạn mọi tệp / thư mục con với thư mục con và bất kỳ tệp ẩn nào ngay bên dưới.

[1:0:248][ebaron@37signals:pts/4][~/Desktop]
$ ls .!(|)
.bash_aliases  .bashrc1  .bashrc1~

..:
askapache-bash-profile.txt  examples.desktop             Public           top-1m.csv
backups             Firefox_wallpaper.png        PycharmProjects          top-1m.csv.zip
Desktop             java_error_in_PYCHARM_17581.log  Shotwell Import Log.txt  topsites.txt
Documents           Music                Templates            Videos
Downloads           Pictures                 texput.log           vmware

Xin lỗi, tôi không thể bình luận. để giải thích sự khác biệt ở đây giữa ls .?*và @ trả lời cioby23 ls -d .[!.]* .??*Và tại sao nó thực sự được in các tập tin ẩn hai lần là vì nghĩa đen bạn đang yêu cầu hai lần .??*, .?*, .[!.]*họ là những điều tương tự, vì vậy thêm bất kỳ trong số họ với các nhân vật khác nhau lệnh sẽ in hai lần.


1

Bạn cũng có thể dùng:

ls -d .[!.]* .??*

Điều này sẽ cho phép bạn hiển thị các tệp ẩn thông thường và các tệp ẩn bắt đầu bằng 2 hoặc 3 dấu chấm chẳng hạn: ..hidden_file


1
Với điều này, tôi nhận được tất cả các tập tin ẩn hai lần.
TuKsn

1

bạn có thể sử dụng lệnh

ls -Ad .??*

Điều này có lợi thế là cho phép liệt kê nhiều cột, không giống như cách tiếp cận dựa trên grep trong các ls -a | grep "^\."giải pháp


1

Tất cả các câu trả lời cho đến nay đều dựa trên thực tế là các tệp (hoặc thư mục) mà tên bắt đầu bằng dấu chấm bị "ẩn". Tôi đã đưa ra một giải pháp khác, có thể không hiệu quả, nhưng giải pháp này không giả sử bất cứ điều gì về tên của các tệp ẩn và do đó tránh được việc liệt kê ..trong kết quả (như câu trả lời hiện được chấp nhận).

Lệnh đầy đủ là:

ls -d $(echo -e "$(\ls)\n$(\ls -A)" | sort | uniq -u)

Giải trình

Những gì nó làm là liệt kê tất cả các tệp (và thư mục) hai lần,

echo -e "$(\ls)\n$(\ls -A)"

nhưng chỉ hiển thị các tập tin ẩn một lần -A.

Sau đó, danh sách được sắp xếp | sortlàm cho các tệp thông thường (không bị chặn) xuất hiện hai lần và cạnh nhau.

Sau đó, xóa tất cả các dòng xuất hiện nhiều lần | uniq -u, chỉ để lại các dòng duy nhất.

Cuối cùng sử dụng lslại để liệt kê tất cả các tệp có tùy chọn tùy chỉnh của người dùng và không liệt kê nội dung của các thư mục trong danh sách -d.

EDIT (Hạn chế):

Như muru đã chỉ ra, giải pháp này sẽ không hoạt động chính xác nếu có các tệp có tên như escaped\ncharacter.txtecho -esẽ chia tên tệp thành hai dòng. Nó cũng sẽ không hoạt động như mong đợi nếu có hai tệp ẩn có cùng tên gần như ngoại trừ một ký tự đặc biệt, chẳng hạn như .foo[tab].txt.foo[new-line].txtcả hai tệp được in .foo?.txtvà sẽ bị loại bỏ bởiuniq -u


1
Tôi nghĩ đó là khá nhiều định nghĩa của các tập tin ẩn. Ngay cả nguồn gốc của các tập tin ẩn này là từ một lỗi trong việc xử lý .như là ký tự đầu tiên.
muru

Tôi đề cập đến điều đó (như thực tế) trong đoạn đầu tiên. Tuy nhiên, nó vẫn nhận được một kết quả khác với câu trả lời được chấp nhận hiện tại
alejandro

Chắc chắn, nó loại trừ .., nhưng tôi tự hỏi nó hoạt động tốt như thế nào với tên tệp chứa các ký tự đặc biệt.
muru

Tôi không biết chính xác ý của bạn về các ký tự đặc biệt, nhưng tôi nghĩ nó sẽ không gây ra vấn đề gì, vì giải pháp này không giả định bất cứ điều gì về tên tệp
alejandro

Trên thực tế, bạn có giả định ít nhất một điều: tên tệp không có dòng mới trong đó. Ngoài ra: tên tệp không có chuỗi thoát trong đó echo -esẽ giải thích. Ngoài ra: lssẽ không mang tên tệp để hai tên tệp khác nhau được hiển thị giống nhau (ví dụ: trong một số phiên bản lssẽ sử dụng ?cho các ký tự đặc biệt, vì vậy .foo\tbar( \t=> tab) và .foo\nbar( \n=> dòng mới) sẽ hiển thị dưới dạng foo?bar).
muru

1

Ngoài ra, bạn cũng có thể sử dụng echo .*

ví dụ

user@linux:~$ echo .*
. .. .bash_aliases .bash_history .bash_logout .bashrc
user@linux:~$

Nếu bạn thích nó ở định dạng danh sách dài, chỉ cần chuyển đổi khoảng trắng sang một dòng mới.

user@linux:~$ echo .* | tr ' ' '\n'
.
..
.bash_aliases
.bash_history
.bash_logout
.bashrc
user@linux:~$ 

0

Với bash, việc đặt GLOBIGNOREbiến đặc biệt là một số giá trị không trống là đủ để làm cho nó bỏ qua ...khi mở rộng các khối. Từ các tài liệu Bash :

Biến GLOBIGNOREshell có thể được sử dụng để hạn chế tập hợp tên tệp khớp với mẫu. Nếu GLOBIGNOREđược đặt, mỗi tên tệp phù hợp cũng khớp với một trong các mẫu trong GLOBIGNOREsẽ bị xóa khỏi danh sách khớp. Nếu nocaseglobtùy chọn được đặt, việc khớp với các mẫu trong GLOBIGNOREđược thực hiện mà không liên quan đến trường hợp. Tên tệp ...luôn bị bỏ qua khi GLOBIGNOREđược đặt và không null. Tuy nhiên, cài đặt thành GLOBIGNOREgiá trị khác null có tác dụng cho phép tùy chọn shell dotglob, vì vậy tất cả các tên tệp khác bắt đầu bằng ‘.'sẽ khớp.

Nếu chúng ta đặt nó thành .:.., cả hai ...sẽ bị bỏ qua. Vì đặt nó thành bất cứ thứ gì khác null cũng sẽ có hành vi này, chúng tôi cũng có thể đặt nó thành.

Vì thế:

GLOBIGNORE=.
ls -d .*
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.