iconoclast Asked: 2022-03-06 15:36:12 +0800 CST2022-03-06 15:36:12 +0800 CST 2022-03-06 15:36:12 +0800 CST 如何让 zsh globbing 忽略 .DS_Store 之类的文件 772 大多数时候,我喜欢(一方面)在 iTerm 的 BSD 变体上运行 zsh 的组合,但(另一方面)让 macOS 体验可用于不运行或不生产的应用程序感觉在终端中运行。 但让我发疯的一件事是.DS_StoremacOS 到处转储的可怕文件。 我可以配置 zsh 以便如果我键入(例如)nvim *tab,*扩展 而不包括我希望避免的任何文件?(这可能包括.DS_Store,Icon?以及我现在想不到的其他可能。) 我不是在问如何在现场构建一个排除某些文件的模式(示例here、here和here),而是如何让所有 glob 始终排除某些文件。 zsh wildcards 1 个回答 Voted Best Answer Gilles 'SO- stop being evil' 2022-03-08T12:55:07+08:002022-03-08T12:55:07+08:00 dot_glob除了选项之外,您不能自定义 globbing 本身。这是 ATT ksh 和 bash 中存在但 zsh 中不存在的少数功能之一。所以echo *会一直显示Icon1。 您可以忽略完成中的模式,但是当涉及通配符时它会变得复杂。让我们从简单的事情开始:不涉及通配符的补全。使用以下.zshrc, 文件喜欢.DS_Store并且Icon1除非没有其他匹配项,否则不会提供完成。 autoload -zU compinit compinit zstyle ':completion::complete:*:*:files' ignored-patterns '.DS_Store' 'Icon?' zstyle ':completion::complete:*:*:globbed-files' ignored-patterns '.DS_Store' 'Icon?' zstyle ':completion::complete:rm:*:globbed-files' ignored-patterns 说明:我定义完成样式: 他们在完成时适用。 它们适用于“功能”为空的情况(这不包括一些特殊的小部件)。 它们适用于进行普通补全 ( _complete),而不是例如更正或_ingore。 它们适用于除rm. 对于该rm命令,上面的代码片段定义了一个空的忽略列表,它会覆盖默认值。 它们适用于命令行上的任何位置。 它们适用于收集文件名(通过 tag_files或 tag _globbed-files)。 这些样式不适用于通配符扩展。默认情况下,通配符扩展Tab会绕过完成代码。要使其使用完成代码,特别是_expand完成者,您需要绑定Tab并complete-word使用_expand使用expansions标签的完成者。 autoload -zU compinit compinit bindkey '^I' complete-word zstyle ':completion:::::' completer _expand _complete _ignored zstyle ':completion::expand:*:*:expansions' ignored-patterns '.DS_Store' 'Icon?' zstyle ':completion::expand:*:*:all-expansions' ignored-patterns '.DS_Store' 'Icon?' 这样,在包含和的.zshrc目录中,.DOH循环通过、和。由于标签上的样式,在循环浏览单个扩展时会被忽略。当扩展到匹配列表时,有一个标签适用,但不幸的是它不支持. (实际上,它确实如此,但以一种无用的方式:它可用于删除整个匹配列表,而不是从中删除单个元素。).DS_Store.zshrcecho .*Tab.DOH.zshrc.DOH .DS_Store .zshrc.*ignored-patternsexpansions.DS_Storeall-expansionsignored-patterns 我发现从所有扩展列表中过滤掉匹配项的唯一方法是修补_expand函数。 diff --git a/Completion/Base/Completer/_expand b/Completion/Base/Completer/_expand index e5e4f9b39..df6f55a7d 100644 --- a/Completion/Base/Completer/_expand +++ b/Completion/Base/Completer/_expand @@ -107,7 +107,13 @@ subd=("$exp[@]") integer done_quote local -a orig_exp=( $exp ) if [[ "$force" = *g* ]] || zstyle -T ":completion:${curcontext}:" glob; then - eval 'exp=( ${~exp//(#b)\\([ \"'"\'"' + local -a exps igns + exps=($~exp) + zstyle -a ":completion:${curcontext}:all-expansions" ignored-patterns igns + if (($#igns)); then + eval "exps=(\${exps:#(${(j:|:)igns})})" + fi + eval 'exp=( ${exps//(#b)\\([ \"'"\'"' ])/$match[1]} ); exp=( ${(q)exp} )' 2>/dev/null && (( $#exp )) && done_quote=1 fi # If the globbing failed, or we didn't try globbing, we'll do 有了这个补丁和.zshrc上面的补丁,all-expansions标签确实会.DS_Store被echo .* Tab. 请注意,我只对这个补丁进行了最低限度的测试。它可能会破坏其他东西。它可能不适用于某些配置。它可能无法正确引用文件名。
dot_glob
除了选项之外,您不能自定义 globbing 本身。这是 ATT ksh 和 bash 中存在但 zsh 中不存在的少数功能之一。所以echo *
会一直显示Icon1
。您可以忽略完成中的模式,但是当涉及通配符时它会变得复杂。让我们从简单的事情开始:不涉及通配符的补全。使用以下
.zshrc
, 文件喜欢.DS_Store
并且Icon1
除非没有其他匹配项,否则不会提供完成。说明:我定义完成样式:
_complete
),而不是例如更正或_ingore
。rm
. 对于该rm
命令,上面的代码片段定义了一个空的忽略列表,它会覆盖默认值。_files
或 tag_globbed-files
)。这些样式不适用于通配符扩展。默认情况下,通配符扩展Tab会绕过完成代码。要使其使用完成代码,特别是
_expand
完成者,您需要绑定Tab并complete-word
使用_expand
使用expansions
标签的完成者。这样,在包含和的
.zshrc
目录中,.DOH
循环通过、和。由于标签上的样式,在循环浏览单个扩展时会被忽略。当扩展到匹配列表时,有一个标签适用,但不幸的是它不支持. (实际上,它确实如此,但以一种无用的方式:它可用于删除整个匹配列表,而不是从中删除单个元素。).DS_Store
.zshrc
echo .*
Tab.DOH
.zshrc
.DOH .DS_Store .zshrc
.*
ignored-patterns
expansions
.DS_Store
all-expansions
ignored-patterns
我发现从所有扩展列表中过滤掉匹配项的唯一方法是修补
_expand
函数。有了这个补丁和
.zshrc
上面的补丁,all-expansions
标签确实会.DS_Store
被echo .*
Tab.请注意,我只对这个补丁进行了最低限度的测试。它可能会破坏其他东西。它可能不适用于某些配置。它可能无法正确引用文件名。