Làm thế nào để thêm mẫu để hoàn thành bash (cho giải nén)?


11

Khi tôi gõ

unzip <tab>

Tôi nhận được một danh sách tất cả các tệp kết thúc bằng .zip, đó là hành vi tiêu chuẩn của việc hoàn thành tab cho unziplệnh.

Tuy nhiên, tôi cũng muốn hoàn thành bash cho unzipcác tệp danh sách kết thúc .udp, ngoài .zipcác tệp. Làm thế nào tôi có thể đạt được hành vi này tại địa phương của tôi .bashrc?

Câu trả lời:


22

Thay vì tiếp tục bình luận


complete -f -X '!*.@(zip|udp)' unzip

nên thêm hoàn thành cho

-f -X '!*.@(zip|udp)'
 |  |  | |||________|
 |  |  | ||     |
 |  |  | ||     +- filterpat: zip or udp
 |  |  | |+-------------  @ : Matches one of the given patterns
 |  |  | +-------------- *. : Anything+<dot>
 |  |  +----------------  ! : Negate
 |  +------------------- -X : Filter out matches in "filterpat"
 +---------------------- -f : files

Nói cách khác: Hoàn thành các tệp và loại bỏ tất cả không kết thúc bằng .ziphoặc .udp.


Ngoài ra

Nếu bạn thêm -o defaulthoàn thành sẽ hoàn thành / khớp tất cả các tệp và thư mục nếu không có tệp kết thúc bằng .ziphoặc .udp.

Nếu bạn thêm -o plusdirshoàn thành sẽ thêm bất kỳ thư mục nào ngoài bất kỳ trận đấu nào của tệp kết thúc bằng .ziphoặc .udp.

Hiện hành

Khi bạn sử dụng, complete -p unzipbạn nhận được mô hình hiện tại.

Từ ý kiến ​​của bạn, có vẻ như bạn đang thiếu +hoặc @theo mẫu, như trong:

# Err:
complete -f -X '!*.(zip|udp)' unzip
                   |
                   +---- Missing + or @

có nghĩa là phù hợp với bất kỳ tập tin theo nghĩa đen kết thúc bằng.(zip|udp) . Ví dụ

touch 'file_test.(zip|udp)'

Cũng có một cái nhìn vào phần này của hướng dẫn:

có thể, ví dụ như extglobkhông được kích hoạt. Kích hoạt bằng:

shopt -s extglob

Kiểm tra trạng thái hiện tại của tất cả các shoptcài đặt bằng cách nhập:

shopt

Chức năng

Nếu đó là -F somethingnó có nghĩa là nó sử dụng một hàm có tên một cái gì đó để tạo danh sách hoàn thành.

Các _filedir_xspecthường là một hàm Debian. Bạn có thể có một cái gì đó như thế này:

$ cat /etc/bash_completion
. /usr/share/bash-completion/bash_completion

Có nghĩa là có /usr/share/bash-completion/bash_completionđược nguồn gốc. Ở đây bạn sẽ tìm thấy các chức năng trong câu hỏi . Một vài dòng tiếp theo bạn thấy rằng chức năng / hoàn thành này được thêm bởi một chức năng có tên là _install_xspec: vd:

_install_xspec '!*.@(zip|[ejsw]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|do[ct][xm]|p[op]t[mx]|xl[st][xm])' unzip zipinfo

Hướng dẫn sử dụng:


Cập nhật ý kiến ​​1:

- Không khớp do lưu trữ không hợp lệ hoặc quyền truy cập tệp.

Điều này sẽ không ảnh hưởng đến kết quả. completechỉ khớp với các tệp được đưa ra bởi các quy tắc và không xử lý các tệp. Nếu bạn có thể liệt kê chúng với ls, chúng sẽ phù hợp.

Là một lưu ý phụ người ta có thể thêm một chức năng như vậy bằng cách sử dụng một chức năng hoàn chỉnh:

function _unzip_validated() {
    # 1. Generate list of files ending in e.g. .zip and .udp
    # 2. Validate each file and remove invalid ones from file list.
}

complete -F _unzip_validated unzip

- Màu sắc. Tại sao lsphân biệt test.ziptừ test.upd?

Điều này không ảnh hưởng complete. Màu sắc lsđược cung cấp bởi $LS_COLORS. Thử:

echo "$LS_COLORS" | tr : '\n' | sort

Bạn sẽ thấy một cái gì *.zip=01;31đó có nghĩa là:

*.zip=01;31
|____| |  |
   |   |  +--- Red
   |   +------ Bold
   +---------- Files with .zip extension

*.udp mặt khác không có mục liên quan đến nó, vì vậy không có màu.


Bước tiếp theo (nên là đầu tiên)

  1. Mở terminal và đi đến một thư mục với các tập tin thử nghiệm. Cả .zip và .udp
  2. Đi vào bash --norc
  3. Đi vào complete -f -X '!*.@(zip|udp)' unzip
  4. Đi vào shopt -s extglob
  5. Đi vào unzip <tab><tab>

Kết quả?

Ngoài ra, nhấp vào chỉnh sửa bên dưới câu hỏi của bạn và thêm đầu ra của:

bind -V
shopt
env

có thể hữu ích


Cảm ơn bạn rất nhiều vì lời giải thích tuyệt vời và dài dòng của bạn, nhưng nó vẫn không hoạt động. complete -p unzipmang lại complete -f -X '!*.@(zip|udp)' unzip, và unzip <tab>hoàn thành các tập tin có tên test.zip. Tuy nhiên, thư mục chứa một tệp có tên test.updcũng không được tìm thấy khi hoàn thành tab unzip. Liệu thực tế của quyền truy cập tập tin hoặc độ dài của tập tin có thể giải thích hành vi kỳ lạ này?
Alex

@Alex: Nên hoàn thành cả hai tệp trống và hợp lệ, cũng như trên các tệp không được phép. Đây có phải là hành vi tương tự nếu bạn thêm nó vào một kịch bản thử nghiệm? Ví dụ 1. một số tập lệnh kiểm tra với tập thực thi : ~/bin/testing, 2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium

@ Alex: Bạn cũng có thể cập nhật Q với sản lượng shopt...
Runium

extglobđược kích hoạt. Ví dụ với 'tests' chỉ chọn lại ziptệp. Tôi nhận thấy rằng test.zipđược hiển thị màu đỏ, trong khi test.updđược hiển thị màu trắng với ls -l, cả hai tệp trống với cùng quyền, chủ sở hữu và liên kết nhóm. Tại sao lsphân biệt test.ziptừ test.upd? Có lẽ đây là một gợi ý cho vấn đề tôi có?
Alex

@Alex: Đã thêm một bản cập nhật.
Runium

3

Trong tệp /etc/bash_completionmà bạn có thể tìm nguồn cung ứng ở đâu đó, việc hoàn thành mặc định, ít nhất là cho phiên bản bash(v4.2.25) của tôi là

complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk)' unzip zipinfo

Hãy thử thay đổi toàn bộ biểu thức thành

complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk|udp)' unzip zipinfo

Và thêm vào của bạn .bash_profile


Điều này không giải quyết vấn đề của tôi. Nếu tôi làm như vậy và nguồn nó, unzip <tab>không phát hiện .zipcũng không .updfile hay các file khác.
Alex

Hãy thử nhấn tab hai lần, xem điều đó có khác không. Làm hoàn thành khác làm việc như mong đợi? Ví dụ gzipvới .gztập tin?
bsd

Đánh tab hai lần không thay đổi bất cứ điều gì. Sử dụng gunzipvới .gzcác tệp chỉ chọn các tệp kết thúc bằng .gz, nhưng định nghĩa cũng khác : complete -F _filedir_xspec gunzip.
Alex

Bạn có nguồn các tập tin /etc/bash_completiontrong của bạn .bashrc?
bsd

Hãy thửshopt -s extglob
Edward Falk

2

Hãy thử thêm dòng này vào .bashrc của bạn:

complete -f -o default -X '!*.+(zip|udp)' unzip

Dường như với đề xuất này, tôi sẽ tìm thấy .udpcác tệp, nhưng chỉ khi không có .ziptệp nào. Nếu a test.ziptest.udptệp có trong thư mục hiện tại, unzip <tab>chỉ liệt kê .ziptệp. Tôi hy vọng sẽ thấy cả hai tệp (tức là hoàn thành bash sẽ cung cấp test.).
Alex

Bạn có chắc không? Tôi đã kiểm tra bash của tôi và tôi dường như tìm thấy cả hai udpzipcác tập tin. Bạn đã nguồn .bashrcsau khi thêm dòng?
mkc

Tôi đã lặp lại trong một thiết bị đầu cuối mới và bây giờ unzip <tab>liệt kê tất cả các tệp, ngay cả những tệp kết thúc bằng một cụm từ khác. Bây giờ khá những gì tôi cần.
Alex

Lạ thật .. Tôi đang chạy GNU bash phiên bản 4.2.25 và hoạt động như mong đợi. Bạn đang dùng phiên bản bash nào?
mkc

Bạn có thể thử thêm hai dòng riêng biệt: complete -f -o default -X '!*.zip' unzipcomplete -f -o default -X '!*.udp' unzip
mkc

1

Sử dụng tốt hơn _filedirthay vì "thô" complete.

Biện minh

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • ~đường dẫn tilde ( ) đang được mở rộng
  • Tiền tố được xóa cho các thư mục, tức là /home/tux/Do<TAB><TAB>, danh sách bạn nhận được khi trả lời sẽ xóa '/ home / tux' và do đó gọn hơn rất nhiều
  • Dễ thực hiện hơn và không an toàn hơn

MWE

_unzip_completor()
{
    # init bash-completion's stuff
    _init_completion || return

    # fill COMPREPLY using bash-completion's routine
    _filedir '@(zip|udp)'
}
complete -F _unzip_completor unzip
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.