Bagaimana cara menambahkan pola ke penyelesaian bash (untuk unzip)?

11

Saat saya mengetik

unzip <tab>

Saya mendapatkan daftar semua file yang diakhiri .zip, yang merupakan perilaku standar penyelesaian tab untuk unzipperintah.

Namun, saya juga ingin menyelesaikan bash untuk unzipfile daftar yang berakhiran .udp, selain .zipfile. Bagaimana saya bisa mencapai perilaku ini di lokal saya .bashrc?

Alex
sumber

Jawaban:

22

Alih-alih terus berkomentar ...


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

harus menambahkan penyelesaian untuk

-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

Dengan kata lain: Lengkapi file dan hapus semua yang tidak diakhiri dengan .zipatau .udp.


Ekstra

Jika Anda menambahkan -o defaultpenyelesaian akan menyelesaikan / mencocokkan semua file dan direktori jika tidak ada file yang berakhiran .zipatau .udp.

Jika Anda menambahkan -o plusdirspenyelesaian akan menambah direktori apa pun selain kecocokan file yang berakhiran .zipatau .udp.

Arus

Ketika Anda menggunakan complete -p unzipAnda mendapatkan pola saat ini.

Dari komentar Anda kedengarannya sebagian besar seperti Anda hilang baik +atau @dalam pola, seperti di:

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

yang berarti cocok dengan file apa pun yang benar-benar berakhiran.(zip|udp) . Misalnya

touch 'file_test.(zip|udp)'

Lihat juga bagian manual ini:

mungkin misalnya extglobtidak diaktifkan. Aktifkan oleh:

shopt -s extglob

Periksa status saat ini dari semua shoptpengaturan dengan memasukkan:

shopt

Fungsi

Jika -F somethingitu artinya menggunakan fungsi bernama sesuatu untuk menghasilkan daftar penyelesaian.

The _filedir_xspecbiasanya fungsi Debian. Anda mungkin memiliki sesuatu seperti ini:

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

Yang berarti /usr/share/bash-completion/bash_completionbersumber. Di sini Anda akan menemukan fungsi yang dimaksud . Beberapa baris lebih jauh ke bawah Anda melihat bahwa fungsi / penyelesaian ini ditambahkan oleh fungsi yang dinamai _install_xspecoleh misalnya:

_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

Entri manual:


Perbarui ke komentar 1:

- Tidak ada kecocokan karena arsip atau izin file tidak valid.

Ini seharusnya tidak mempengaruhi hasil. completehanya cocok dengan file yang diberikan oleh aturan dan tidak memproses file. Jika Anda dapat mendaftar mereka ls, mereka harus cocok.

Sebagai catatan tambahan, seseorang dapat menambahkan fungsi seperti itu dengan menggunakan fungsi lengkap:

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

- Warna. Mengapa lsdibedakan test.zipdari test.upd?

Ini tidak mempengaruhi complete. Warna oleh lsdisediakan oleh $LS_COLORS. Mencoba:

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

Anda harus melihat sesuatu *.zip=01;31yang artinya:

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

*.udp di sisi lain tidak ada entri yang terkait dengannya, jadi tidak ada pewarnaan.


Langkah selanjutnya (seharusnya lebih dulu)

  1. Buka terminal dan pergi ke direktori dengan file uji. Baik .zip dan .udp
  2. Memasukkan bash --norc
  3. Memasukkan complete -f -X '!*.@(zip|udp)' unzip
  4. Memasukkan shopt -s extglob
  5. Memasukkan unzip <tab><tab>

Hasil?

Juga, klik edit di bawah pertanyaan Anda dan tambahkan output:

bind -V
shopt
env

mungkin bermanfaat.

Runium
sumber
Terima kasih banyak atas penjelasan Anda yang luar biasa dan panjang, tetapi tetap saja itu tidak berhasil. complete -p unzipmenghasilkan complete -f -X '!*.@(zip|udp)' unzip, dan unzip <tab>melengkapi file bernama test.zip. Namun, direktori tersebut berisi file bernama test.updjuga yang tidak ditemukan oleh tab penyelesaian unzip. Apakah fakta izin file atau panjang nol file mungkin menjelaskan perilaku aneh ini?
Alex
@Alex: Seharusnya mendapatkan penyelesaian pada file kosong dan valid, serta pada file di mana orang tidak memiliki izin. Apakah itu perilaku yang sama jika Anda menambahkannya ke skrip pengujian? Misalnya 1. beberapa skrip pengujian dengan set eksekusi:, ~/bin/testing2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium
@Alex: Anda juga dapat memperbarui Q dengan output dari shopt...
Runium
extglobdiaktifkan. Contoh dengan 'pengujian' memilih zipfile hanya lagi. Saya perhatikan yang test.zipditampilkan dalam warna merah, sementara test.updditampilkan dalam warna putih dengan ls -l, kedua file kosong dengan izin yang sama, pengalihan pemilik dan asosiasi grup. Mengapa lsdibedakan test.zipdari test.upd? Mungkin ini adalah petunjuk terhadap masalah yang saya miliki?
Alex
@Alex: Menambahkan pembaruan.
Runium
3

Dalam file /etc/bash_completion, yang mungkin Anda bashdapatkan dari sumber di suatu tempat, penyelesaian default, setidaknya untuk versi saya (v4.2.25) adalah

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

Coba ubah seluruh ekspresi menjadi

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

Dan tambahkan ke .bash_profile

bsd
sumber
Ini tidak menyelesaikan masalah saya. Jika saya melakukannya dan sumbernya, unzip <tab>tidak menemukan .zipatau .updfile atau file lainnya.
Alex
Coba tekan tab dua kali, lihat apakah itu berbeda. Apakah penyelesaian lainnya berfungsi seperti yang diharapkan? Misalnya gzipdengan .gzfile?
bsd
Menekan tab dua kali tidak mengubah apa pun. Menggunakan gunzipdengan .gzfile pilih hanya file berakhiran .gz, tapi definisi juga berbeda: complete -F _filedir_xspec gunzip.
Alex
Apakah Anda sumber file /etc/bash_completiondi Anda .bashrc?
bsd
Cobashopt -s extglob
Edward Falk
2

Coba tambahkan baris ini di .bashrc Anda:

complete -f -o default -X '!*.+(zip|udp)' unzip
mkc
sumber
Tampaknya dengan saran ini saya akan menemukan .udpfile, tetapi hanya jika tidak ada .zipfile. Jika a test.zipdan test.udpfile ada di direktori saat ini, unzip <tab>hanya daftar .zipfile. Saya akan berharap untuk melihat kedua file (yaitu penyelesaian bash akan memberi test.).
Alex
Apakah kamu yakin Saya memeriksa bash saya dan sepertinya saya menemukan keduanya udpdan zipfile. Apakah Anda sumber .bashrcsetelah menambahkan baris?
mkc
Saya ulangi di terminal baru, dan sekarang unzip <tab>daftar semua file, bahkan yang berakhir dengan frasa yang berbeda. Sekarang cukup apa yang saya butuhkan.
Alex
Aneh .. Saya menjalankan GNU bash versi 4.2.25 dan berfungsi seperti yang diharapkan. Versi bash manakah Anda?
mkc
Bisakah Anda mencoba menambahkan dua baris terpisah: complete -f -o default -X '!*.zip' unzipdancomplete -f -o default -X '!*.udp' unzip
mkc
1

Lebih baik digunakan _filedirdaripada "mentah" complete.

Pembenaran

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • ~jalur tilde ( ) sedang diperluas
  • Awalan dihapus untuk direktori, yaitu untuk /home/tux/Do<TAB><TAB>, daftar yang Anda dapatkan sebagai balasan menghapus '/ home / tux' dan karenanya jauh lebih kompak
  • Lebih mudah diimplementasikan dan lebih banyak failafe

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
Johannes
sumber