завершение zsh :не предлагать каталоги при извлечении архива с помощью tar

Я искал и нашел два полезных ответа; один просто использует tacв конце, а другой представляет собой оператор awk, в котором я не понимаю!

Ответ 1:cat filename | tac

Ответ 2:cat filename | awk '{arr[i++]=$0} END {while (i>0) print arr[--i] }'

Просто интересно, почему не работал sort -r!..

5
08.02.2021, 06:20
1 ответ

Получение от системы завершения представления только файлов для каждого вызова tarявляется относительно простым. Эта команда zstyleдобавлена ​​к .zshrcсделает свое дело:

zstyle ':completion:*:*:tar:*' 'file-patterns' '*(.)'

Это запускает код во встроенной функции _files, который ограничивает шаблон файла соответствует только обычным файлам через квалификатор (.)glob.

К сожалению, он переопределяет соответствие шаблону -для всех tarвызовов, поэтому сопоставление на основе расширения -в вашем примере больше не работает, и каталоги не являются частью сопоставления при создании архива. Изменение zshна более избирательное игнорирование каталогов включает в себя более глубокое изучение код завершения.


Этого можно добиться, изменив _tar_archiveфункцию (благодаря @Gilles за то, что указал, как ). Эта функция уже имеет отдельную обработку для извлечения архивов и создания архивов, поэтому нам просто нужно изменить строки для распаковки архивов.

Это модифицированный код, основанный на коде из моей системы. (macOS 10.15, zsh 5.7.1 ). Он вызывает _path_filesнепосредственно в извлечении случаях, чтобы он просматривал только файлы. Исходный код использовал _files, который перебирал как файлы, так и каталоги.

#autoload

# This is used to generate filenames usable as a tar archive.  This may
# get one argument, a collection of tar option characters that may be
# used to find out what kind of filename is needed.  If no argument is
# given but the parameter `_tar_cmd' is set, that is used.
# If your version of `tar' supports this you may want to complete
# things like `host:file' or `user@host:file' here.

local expl

[[ $# -eq 0 && $+_tar_cmd -ne 0 ]] && set "$_tar_cmd"

_description files expl 'archive file'

if [[ "$1" = *[urtx]* ]]; then
  if [[ "$1" = *[zZ]* ]]; then
    _path_files "$expl[@]" -g '*.((tar|TAR).(gz|GZ|Z)|tgz)(-.)'
  elif [[ "$1" = *[Ijy]* ]]; then
    _path_files "$expl[@]" -g '*.(tar|TAR).bz2(-.)'
  elif [[ "$1" = *J* ]]; then
    _path_files "$expl[@]" -g '*.(tar|TAR).(lzma|xz)(-.)'
  elif [[ "$_cmd_variant[$service]" == (gnu|libarchive) ]]; then
    _path_files "$expl[@]" -g '*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)'
  else
    _path_files "$expl[@]" -g '*.(tar|TAR)(-.)'
  fi
else
  _files "$expl[@]"
fi

Изменение функций в системе заканчивания может быть несколько сложным. Это вероятно, лучше всего создавать копии, а не изменять код выпуска в оригинальные каталоги. Для справки, это команды, которые были необходимо в моей системе; другие системы могут иметь другие требования. Там подробнее в этом ответе Stack Exchange :https://unix.stackexchange.com/a/33898/432774

Одноразовые изменения:

mkdir ~/.zfunc
for d in $fpath; do
  [[ -f $d/_tar_archive ]] && cp $d/_tar_archive ~/.zfunc; break
done
# (edit file as noted above)

print 'fpath=( ~/.zfunc "${fpath[@]}" )' >> ~/.zshrc
# (restart shell)

Эти команды необходимы после каждого изменения кода. Обратите внимание, что просто перезапуск оболочки может быть недостаточно:

unfunction _tar_archive
autoload -Uz _tar_archive

rm ~/.zcompdump
rm ~/.zcompcache/*
compinit
3
18.03.2021, 22:31

Теги

Похожие вопросы