mở rộng vỏ (A | B) trong tên tệp?


9

Có thể mở rộng một orsự lựa chọn trong shell khi đọc một tập tin chẳng hạn.

Điều tôi muốn nói là, ví dụ, grephỗ trợ cú pháp như (A|B)khớp A hoặc B trong một tệp.

Tương tự, nếu tôi có các tệp này:

file1.txt
file2.txt
file3.txt
file4.txt
file5.txt

Tôi có thể làm cat file{1..5}.txttrong bash, vì nó mở rộng phạm vi. Có một cách tương đương để làm điều này chỉ cho một vài tệp?

Ví dụ cat file(1|5).txtvà chỉ in 2 cái đó?

Câu trả lời:


16

Mẫu tên tập tin tiêu chuẩn để khớp với một chữ số[0-9]. Điều này khớp với một chữ số:

cat file[0-9].txt

Để chỉ chọn hai trong số này:

cat file[25].txt

Đối với số lượng lớn hơn 9, mở rộng niềng răng sẽ hữu ích (nhưng xem lưu ý bên dưới để biết sự khác biệt giữa các mẫu hình cầu và mở rộng niềng răng):

cat file{25..60}.txt

Một lần nữa, mở rộng cú đúp cũng cho phép số lượng riêng lẻ:

cat file{12,45,900,xyz}.txt

(lưu ý rằng trong ví dụ trên, việc mở rộng dấu ngoặc không liên quan đến vòng lặp số học, mà chỉ tạo các tên dựa trên các chuỗi được cung cấp).

Trong bash, với extglobtùy chọn shell được bật ( shopt -s extglob), các tùy chọn sau cũng sẽ hoạt động:

cat file@(12|45|490|foo).txt

Các @(...)mẫu sẽ phù hợp với bất kỳ một trong những bao gồm |mẫu -delimited.


Sự khác biệt giữa các mẫu hình cầu [...]@(...)mở rộng dấu ngoặc, là việc mở rộng dấu ngoặc được tạo trên dòng lệnh và có thể không thực sự khớp với bất kỳ tên hiện có nào trong thư mục hiện tại. Một mẫu tên toàn cầu sẽ khớp với tên, nhưng shell sẽ không khiếu nại nếu không tồn tại tất cả tên có thể. Nếu không có tên phù hợp tồn tại, mẫu sẽ vẫn chưa được mở rộng, trừ khi nullglobtùy chọn shell được đặt, trong trường hợp đó mẫu sẽ bị xóa.

Thí dụ:

touch file1

ls file[0-9]

Ở đây, chỉ có danh sách tập tin cho file1sẽ được hiển thị.

Với ls file{0..9}, lssẽ phàn nàn về việc không tìm thấy file0, file2vv

Trong ví dụ sau, lệnh đầu tiên sẽ chỉ chạm vào các tên hiện có khớp với mẫu đã cho, trong khi dòng thứ hai sẽ tạo các tệp chưa tồn tại:

touch file[0-9]

touch file{0..9}

@thecarpy Tôi xin lỗi, nhưng đó không phải là một mẫu phù hợp với ví dụ file45.txt. Biểu thức ngoặc [...]hoạt động giống như trong biểu thức thông thường nhưng sử dụng !thay ^cho cụm từ "không trong". Một [...]mô hình sẽ luôn luôn phù hợp với một nhân vật duy nhất.
Kusalananda

Bạn đúng rồi! BTW, tôi {1,2}cũng không tuân thủ POSIX ... đã học được một vài điều mới ngày hôm nay!
thecarpy

2
Thực tế là việc mở rộng dấu ngoặc không cần phải khớp với các tệp thực có thể cực kỳ hữu ích, nếu bạn đang sử dụng nó để (ví dụ) tạo các mẫu để truyền đến grep, tạo URL để chuyển đến curl, v.v ... nhưng nó cũng có thể gây nhầm lẫn cho những người đã quen làm việc với sự hả hê.
Kevin

@Kevin Đúng. Một mở rộng cú đúp không cần phải là về tên tập tin.
Kusalananda

7

Cú pháp sử dụng là file{1,2}sẽ đánh giá file1file2.

$ ls
$ touch file{1,2,3,4,5,6,7,8,9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

Như Inian đã chỉ ra bên dưới cũng vậy ... sẽ dễ thực hiện hơn touch file{1..9}trong trường hợp ví dụ này ...

$ ls
$ touch file{1..9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

Bạn cũng có thể sử dụng nhiều biểu thức, như:

$ ls
$ touch file{1..9}{a..z}
$ ls
file1a file1b file1c
[...]
file9x file9y file9z

Có, ở trên sẽ tạo ra các tệp 234 ( 9lần 26).


1
Đây file{1,2} cú pháp cũng thuận tiện đến các tập tin đổi tên:mv some_very_long_filename.txt{,.bak}
Eric Duminil

6

Có, bạn có thể sử dụng mở rộng nẹp trong bashvỏ. Đối với chỉ một vài tệp chỉ cần làm file{1..2}hoặc chỉ làfile{1,2}

Hoặc nếu bạn lo lắng về các tệp không có trong một số trường hợp, chỉ cần thực hiện một vòng lặp đơn giản,

for file in file{1..4}.txt; do
    [ -f "$file" ] || continue
    echo "$file" # Do other actions on file here
done

Hoặc nếu chỉ ghép nối là thao tác duy nhất của bạn trên các tệp và nếu bạn không chắc chắn tệp nào không thể có mặt tại bất kỳ thời điểm nào, chỉ cần catchúng và loại bỏ các lỗi. Định hướng lại lỗi tiêu chuẩn để /dev/nullloại bỏ các lỗi nếu tệp không có sẵn.

cat file{1,5}.txt 2>/dev/null

hoặc sử dụng biểu thức toàn cầu file[15]không khiếu nại về các lỗi nếu không tìm thấy tệp.

cat file[15].txt

2
Không, không có lo ngại về các tệp không có ở đó, tôi chỉ muốn hiển thị nội dung của 2 tệp được đánh số thứ tự, nhưng điều đó không liên tiếp, vì vậy file{1,5}cú pháp dấu phẩy là tất cả những gì tôi thiếu!
Joe Healey
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.