명령 완성 시스템은 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
한 가지 변경사항:
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