Làm cách nào để liệt kê mọi tệp trong một thư mục ngoại trừ những tệp có phần mở rộng được chỉ định?


28

Giả sử rằng tôi có một thư mục chứa .txt , .pdf và các tệp khác. Tôi muốn liệt kê các tệp "khác" (nghĩa là các tệp không có phần mở rộng .txt hoặc .pdf ). Bạn có lời khuyên nào về cách làm việc này không?

Tôi biết cách liệt kê các tệp không có phần mở rộng nhất định. Ví dụ: nếu tôi muốn liệt kê tất cả các tệp ngoại trừ các tệp .txt , thì một trong hai

find -not -iname "*.txt"

hoặc là

ls | grep -v '\.txt$' | column

dường như làm việc Nhưng, làm thế nào tôi có thể liệt kê tất cả mọi thứ trừ .txt file hoặc .pdf file? Có vẻ như tôi cần sử dụng một số loại logic "hoặc" trong findhoặc grep.


2
Hãy nhớ rằng hành vi của lsvs findvs globalbing có thể khác nhau đối với các dotfiles ẩn.
jw013

1
Một điều khác cần ghi nhớ: findsẽ duyệt qua các thư mục con, giống như một đệ quy ls. Sử dụng -maxdepth 1với findđể có được nó để hành xử giống như ls.
jw013

Vì vậy, không có đệ quy, chỉ liệt kê các tập tin trong thư mục hiện tại?
cúc

Câu trả lời:


28

Giả sử một cái có phiên bản phù hợp ls, đây có thể là cách đơn giản nhất:

ls -I "*.txt" -I "*.pdf"

Nếu bạn muốn lặp lại tất cả các thư mục con:

ls -I "*.txt" -I "*.pdf" -R

8
lsTùy chọn GNU không di động.
bahamat

4
lsDù sao thì nó không thực sự thuộc về các tập lệnh di động, vì vậy tôi đã giả sử OP chỉ hỏi về việc sử dụng tương tác.
jw013

1
Tại sao ls không di động? Tôi nên sử dụng cái gì sau đó?
Freedo

28

Tìm hỗ trợ -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

Bạn cần dấu ngoặc đơn để làm cho quyền ưu tiên. Tìm làm rất nhiều thứ; Tôi đề nghị đọc qua trang chủ của nó.

Bạn cũng có thể thực hiện một hoặc trong grep(nhưng thực sự, bạn không nên phân tích đầu ra củals )

ls | grep -Ev '\.(txt|pdf)$' | column

1
Cảm ơn! Tại sao tôi không nên phân tích đầu ra ls?
Andrew

6
@Andrew trước, vì nó dễ vỡ (hãy xem xét một tên tệp có dòng mới trong đó Có, đó là tên tệp hợp lệ mà thôi find find -print0 / -exec / -delete / v.v. tránh vấn đề đó); thứ hai, bởi vì thường có một cách dễ dàng hơn.
derobert

Ngoài findtrang này, tôi hết lòng giới thiệu các bài viết về Unix Power Tools về find, chẳng hạn như docstore.mik.ua/orelly/unix3/upt/ch09_06.htmlmdocstore.mik.ua/orelly/unix3/upt/ch09_12.htm
Ký tự đại diện

Chỉ để giúp giải mã tuyên bố cho con người:find . NOT ( *.txt OR *.pdf )
wvducky

12

Với việc bashmở rộng toàn cầu (bật với shopt -s extglob), toàn cầu !(*.txt|*.pdf)sẽ hoạt động. Bạn có thể truyền trực tiếp quả cầu này cho bất kỳ lệnh nào có tham số tệp, bao gồm nhưng không giới hạn ls.


1
+1 nhưng nếu bạn có thư mục con thì nội dung của chúng cũng sẽ được liệt kê; sử dụng -dđể tránh điều đó:ls -d !(*.txt|*.pdf)
huyền thoại2k

Cảm ơn bạn, tôi đã tìm chính xác cú pháp để chấp nhận nhiều tệp, điều này sẽ rất phù hợp ở đây stackoverflow.com/questions/216995/iêu
Freedo

6

Trong zshvới extendedglob:

print -rl -- *~*.(txt|pdf)

hoặc là

print -rl -- ^*.(txt|pdf)

Hoặc với kshglob(vâng, đó là ksh continbing không phải là "bash continbing"):

print -rl -- !(*.txt|*.pdf)

Hãy nhớ rằng những người cũng loại trừ các tập tin dấu chấm.

ksh93 có FIGNOREtính năng (mis):

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *

4
find /path/to/directory '!' -name '*.pdf' '!' -name '*.txt'

Điều này tương đương với lệnh với toán tử OR, vì luật của De Morgan .


3

Theo đề xuất của derobert, đặt cược tốt nhất của bạn là sử dụng find. Tuy nhiên, trên thực tế bạn có thể sử dụng kết quả trong một đường ống với các lệnh khác.

GNU (và một số BSD) findhỗ trợ -print0vị từ yêu cầu nó in tên tệp được chấm dứt bởi một ký tự NUL , ký tự này không được phép trong tên tệp và đảm bảo sẽ không có xung đột. Các lệnh khác có thể được hướng dẫn sử dụng NUL làm dấu phân cách đầu vào của chúng.

Điều quan trọng nhất trong số đó là GNU xargs, chạy lệnh bạn chỉ định và chuyển cho nó danh sách các tệp dưới dạng đối số dòng lệnh. Bạn muốn chạy xargs -r0kết hợp với find -print0Ví dụ:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

Điều này an toàn in một danh sách thư mục dài của tất cả các tệp pdftxt , bao gồm cả những tệp có dấu cách hoặc ký tự không thể in trong tên.

Bạn cũng có thể sử dụng nó với GNU tarnhư sau:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

Điều này xây dựng một tệp tar.gz của tất cả các tệp có tên không kết thúc bằng .tar.gz

rsynccũng chấp nhận các tệp được phân tách bằng null với -0tham số, cũng như một số tệp khác. Nhưng xargslà keo bạn sẽ thường sử dụng cho loại mục đích này. Hoặc là có hoặc find's -exectính năng.


Các tarví dụ lệnh là một tốt nhất. Đối với hầu hết các mục đích, mặc dù, -execlà một phù hợp tốt hơn.
tự đại diện

1

Nếu bạn không có thư mục con

ls !(*.pdf|*.txt)

cũng nên làm việc!

Nhưng

ls -I "*.pdf" -I "*.txt"

là cách phổ biến.


0

Như một sự bổ sung, nếu bạn sử dụng trình bao tương thích bash, bạn có thể sử dụng biến GLOBIGNORE để làm nổi bật các kết nối lại từ khớp mẫu. Từ người đàn ông:

   GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames
          to be ignored by pathname expansion.  If a filename matched by a
          pathname  expansion  pattern also matches one of the patterns in
          GLOBIGNORE, it is removed from the list of matches.

Trong trường hợp cụ thể của bạn:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

Xin lưu ý rằng tôi chạy lệnh đó dưới dạng shell phụ (sử dụng dấu ngoặc đơn) để không thay đổi biến môi trường GLOBIGNORE của shell tương tác của tôi.

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.