Bash: ls * không có nhóm thư mục


12

Nếu tôi gõ:

ls source/*

source/fonts:
fontello

source/images:
bg1.png                eng.png        fra.png   

Tôi nhận được danh sách các tập tin, được nhóm theo tên thư mục. Làm thế nào tôi có thể chỉ cần có được danh sách các tên tập tin?

ls source/*

source/fonts/fontello
source/images/bg1.png
source/images/eng.png
source/images/fra.png   

Cảm ơn


Nếu đây là để sử dụng kịch bản, bạn có thể muốn xem mywiki.wooledge.org/ParsingLs . (Điều đó nói rằng, có nhiều cách để sử dụng findsai; đặc biệt, nếu bạn đang chạy for file in $(find ...), bạn đã nhấn một trong số chúng).
Charles Duffy

Câu trả lời:


13

Có vẻ như không thể thực hiện được nếu không có sự thay đổi đầu ra, nhưng đây là một cách thay thế dễ dàng:

find source/ -type f

Hoặc (cụ thể cho GNU find), để chỉ nhận các tệp ở độ sâu trong câu hỏi của bạn:

find source/ -type f -mindepth 2 -maxdepth 2

(hoặc nếu bạn muốn các thư mục như lscung cấp cho bạn, hãy xóa -type f)


5

Bạn chỉ có thể dính vào ls nếu bạn thêm một số psychedlics ( ls -d):

# mkdir test
# cd test
# mkdir A B C
# touch {A,B,C}/file*
# ls -d */*    
A/file  B/file  C/file

@Cthulhu ok ví dụ của tôi quá ngắn, Nếu bạn có các thư mục trong A, B a / o C, -d sẽ chỉ hiển thị những gì bạn đã chọn. Tôi thực sự không thích tìm và bạn có thể xác định độ sâu bằng đối số với ls -d
ikrabbe

Tôi đã đề nghị chỉnh sửa câu trả lời khác để giới hạn độ sâu.
o11c

@ o11c rất tốt, nhưng vẫn findlà một con thú béo.
ikrabbe

3

Bạn có thể quan tâm đến những người nghèo của người nghèo find:

shopt -s globstar

shopt -s s ets tùy chọn shell được đặt tên (s). Các globstartùy chọn được định nghĩa như sau trong bash (1) :

Nếu được đặt, mẫu **được sử dụng trong ngữ cảnh mở rộng tên tệp / tên đường dẫn sẽ khớp với tệp [sic] và không hoặc nhiều thư mục và thư mục con. Nếu mẫu được theo sau bởi một /, chỉ các thư mục và thư mục con phù hợp.

Vì vậy, sau khi bạn thực hiện xong shopt -s globstar, bất kỳ lệnh nào sau đây:

ls -d1 - source / **                  # Ký tự sau 'd' là chữ số. 
ls -d - nguồn / ** | cat             # tức là nó sẽ ghi nó vào một ống dẫn tới bất kỳ lệnh nào. 
nguồn in "% s \ n" / **

sẽ tạo ra đầu ra:

source/
source/fonts
source/fonts/fontello
source/images
source/images/bg1.png
source/images/eng.png
source/images/fra.png

Thật không may, điều này bao gồm cả tên thư mục. Nó có thể giúp bạn một chút để biết rằng

printf "%s\n" source/**/

sẽ tạo ra đầu ra:

source/
source/fonts
source/images

tức là chỉ có tên thư mục Bạn có thể chuyển hướng đầu ra của một trong những tập đầu tiên của lệnh vào một tập tin, chuyển hướng đầu ra của trên vào một tập tin thứ hai, và sau đó sử dụng comm, diffhoặc một cái gì đó tương tự, trừ các tập tin thứ hai từ đầu tiên, chỉ để lại đơn giản tập tin (không phải thư mục). Nhưng đừng làm vậy.

Một cách tiếp cận khác (không tốt hơn nhiều ) là

ls -d --file-type -- source/** | grep -v '/$'

Các --file-typetùy chọn cho lshiển thị một / vào cuối mỗi tên thư mục (và các nhân vật khác ở tận cùng khác (đặc biệt) các loại tập tin), như sau:

nguồn //                             # Đã thêm một 
nguồn / phông chữ /                        # Đã thêm một nguồn
nguồn / phông chữ / fontello
nguồn / hình ảnh /                       # Đã thêm một
nguồn / hình ảnh / bg1.png
nguồn / hình ảnh / eng.png
nguồn / hình ảnh / fra.png

và sau đó grep -v '/$'loại bỏ các dòng kết thúc bằng /; tức là tên thư mục Thật không may, --file-typetùy chọn không được chỉ định bởi POSIX . Nếu phiên bản của lsbạn không hỗ trợ nó, hãy sử dụng -F. Điều đó giống như --file-type ngoại trừ nó cũng hiển thị *ở cuối tên của các tệp thực thi, điều mà một số người thấy khó chịu. Bạn có thể loại bỏ chúng bằng sed:

ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'

Nếu bạn muốn làm một cái gì đó với tất cả các tệp (và chỉ các tệp), bạn có thể làm

cho f trong nguồn / **
làm
    nếu [-f "$ f"]
    sau đó
        Chèn các lệnh sẽ được áp dụng cho các tập tin đơn giản ở đây.
    fi
làm xong

Ghi chú:

  • Khi lsxuất ra một thiết bị đầu cuối và nó không ở chế độ -l( l ong), nó sẽ ghi nhiều tên trên mỗi dòng (trừ khi các tên rất dài). Bạn có thể buộc nó viết một tên trên mỗi dòng bằng cách chỉ định -1(một) hoặc bằng cách chuyển hướng đầu ra sang tệp hoặc đường ống.
  • Bạn có lẽ không thực sự cần --trong lslệnh kể từ khi bạn đang liệt kê một thư mục có nội dung mà bạn đã tạo. Bạn nên sử dụng nó khi liệt kê *trong một thư mục không xác định, vì bảo vệ chống lại tên tệp bắt đầu bằng -.
  • Đừng cố phân tích đầu ra từ ls.
  • Các globstartùy chọn vỏ dường như không được định nghĩa bởi POSIX. (Trên thực tế, tôi không chắc POSIX nhận ra bất kỳ tùy chọn shell nào .) Mặc dù có vẻ như là một bashism, hãy cẩn thận - nó có thể không có trong tất cả các phiên bản bash.
  • Nếu fontshoặc imagescó các thư mục con, **sẽ liệt kê tất cả, theo cách đệ quy, tất cả các đường dẫn xuống. Một cách (hơi khó hiểu và không đáng tin cậy) để giới hạn độ sâu là

    ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
    

    trong đó loại bỏ các dòng chứa ba hoặc nhiều /ký tự.

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.