コマンド完成システムはtar
非常に賢いです。さまざまなアーカイブタイプがある場合は、使用されているtarオプションに基づいて関連ファイルを提供します。
$ ls
file.tar.xz
file.tar.gz
$ tar xJf f<TAB>
file.tar.xz
$ tar xzf f<TAB>
file.tar.gz
ファイルxJf
に対する操作を認識し、ファイルに対する操作を実行します。tar.xz
xzf
tar.gz
ただし、ディレクトリが現在の場所に存在するときに完了のために提供することもあります。
$ tar xJf f<TAB>
foo/ file.tar.xz
アーカイブを抽出するときにのみファイルが完成したいと思うことを完成システムに通知できますか(tar
オプションx...
)。
ただし、アーカイブを作成するときは、まだディレクトリ(tar
オプション)を提供する必要がありますc...
。
tar cpJf foo.tar.xz
私の考えでは、tar
コマンドの基本的な完成ファイルである/usr/share/zsh/functions/Completion/Unix/_tar
。しかし、どのように?
答え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
1つの変更点:
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