【问题标题】:Path doesn't work with %20 for space in filename in Git console路径不适用于 Git 控制台中文件名中的空间的 %20
【发布时间】:2025-12-15 07:20:15
【问题描述】:

我的文件名包含一个空格,所以当我执行以下操作时:

git add first%20file.txt

上面的命令在我的控制台中返回了无效路径

【问题讨论】:

  • 那么问题是什么?为什么它不起作用?因为您只使用 "%20" 来转义 URL 中的空格,而不是命令行上的文件名中的空格。

标签: git


【解决方案1】:

逃出空间怎么样:

git add first\ file.txt

【讨论】:

    【解决方案2】:

    正如 sschuberth 在 cmets 中提到的 - 您只能使用 %20 来转义 URL 中的空格,而不是命令行上的文件名中的空格。

    您有两个选项来添加这些文件

    1) 文件名中的转义空格

    git add first\ file.txt
    git add first\ file\ name.txt
    

    2) 在引号内添加文件名

    git add "first file.txt"
    git add "first file name.txt"
    

    FWIW,如果您只有一个名称以字符串 first 开头的文件,您也可以使用制表符完成

    【讨论】:

      【解决方案3】:

      Git 2.18 应该改进文件名中带有空格的文件的完成。
      (而且 Git 2.21,Q1 2019,也应该看到这个答案的第二部分)

      请参阅commit f12785a(2018 年 4 月 16 日)SZEDER Gábor (szeder)

      完成:改进命令行中引用路径的处理

      我们的 git 感知路径完成在它必须完成一个 已经包含引号和/或反斜杠转义字符的单词 命令行。
      问题的根本原因是完成函数逐字查看命令行上的所有单词,即包括所有反斜杠、单引号和双引号字符,shell 在执行完成的命令时最终会删除这些字符。
      这些引用/转义字符会导致不同的问题,具体取决于 要完成的单词的路径组件包含它们:

      • 引用/转义位于前缀路径组件中。
        假设我们有一个名为“New Dir”的目录,其中包含两个未跟踪的文件“file.c”和“file.o”,并且我们有一个忽略目标文件的 gitignore 规则。
        在这种情况下,所有这些:

        git add New\ Dir/<TAB>
        git add "New Dir/<TAB>
        git add 'New Dir/<TAB>
        

      应该立即唯一完成“file.c”,但 Bash 同时提供“file.c”和“file.o”。
      这种行为的原因是我们的完成脚本使用前缀目录名称,如“git -C "New\ Dir/" ls-files ...”,即双引号内的反斜杠。
      然后 Git 尝试输入一个名为“New\ Dir”的目录,但(很可能)失败了,因为这样的目录不存在。
      结果,我们的完成脚本没有列出任何文件,将 COMPREPLY 数组留空,这反过来又导致 Bash 回退到其简单的文件名完成并列出该目录中的所有文件,即 'file.c' 和'file.o'。

      • 引用/转义在要完成的路径组件中。
        假设我们有两个未跟踪的文件“New File.c”和“New File.o”,并且我们有一个忽略目标文件的 gitignore 规则。
        在这种情况下,所有这些:

        git add New\ Fi<TAB>
        git add "New Fi<TAB>
        git add 'New Fi<TAB>
        

      应该立即唯一地完成“New File.c”,但 Bash 同时提供“New File.c”和“New File.o”。
      这种行为的原因是我们的完成脚本使用这个'New\ Fi'或'"New Fi'等词来过滤匹配的路径,当然,由于包含反斜杠或双引号,任何潜在的文件名都不会匹配。
      最终结果和上面一样:
      完成脚本没有列出任何文件,Bash 回退到它的文件名完成,然后也列出匹配的目标文件。

      添加新的辅助函数__git_dequote(),它会从作为参数的单词中删除引用和转义。
      为了最大限度地减少调用此函数的开销,请将其结果存储在 变量$dequoted_word,应该在 呼叫者;简单地打印结果需要一个命令 替换强加了 fork() 子 shell 的开销。
      __git_complete_index_file() 中使用这个函数来取消引用当前单词, 即要完成的路径,以避免上述情况 引用相关的问题,从而修复两个失败的引用路径 完成测试。


      Git 2.21(2019 年第一季度)将改进 zsh "git cmd path&lt;TAB&gt;",它已完成为 "git cmd path name"当完成的路径中有特殊字符如 SP 时,无需任何尝试保留“path name”一个文件名。

      这已修复为“git cmd path\ name”,就像 bash 完成。

      参见Chayoung You (yous)@commit 6d54f52commit 7a478b3(2019 年 1 月 1 日)。
      (由 Junio C Hamano -- gitster -- 合并到 commit b84e297,2019 年 1 月 18 日)

      completion:将@​​987654360@ 的结果视为文件路径

      假设有文件名为“foo bar.txt”和“abc def/test.txt”在 存储库。
      当以下命令触发完成时:

      git show HEAD:fo<Tab>
      git show HEAD:ab<Tab>
      

      bash/zsh 中的补全结果:

      git show HEAD:foo bar.txt
      git show HEAD:abc def/
      

      它们在路径中都有一个未转义的空格,所以它们会被 Git 误读。
      git ls-tree 的所有条目都是文件名或目录,因此 __gitcomp_file() 是正确的而不是 __gitcomp_nl()

      注意commit f12785a, Git v2.18.0-rc0,它可以正确处理引用的路径。
      像这种情况,我们应该为?*:* 的情况取消引用$cur_

      例如,假设有未跟踪的目录'abc deg',则触发完成:

      git show HEAD:abc\ de<Tab>
      git show HEAD:'abc de<Tab>
      git show HEAD:"abc de<Tab>
      

      应该唯一地完成 'abc def',但 bash 会完成 'abc def' 和 'abc deg'。

      在zsh中,触发完成:

      git show HEAD:abc\ def/<Tab>
      

      应该完成'test.txt',但什么都没有。
      这两个问题都将通过取消引用路径来解决。

      __git_complete_revlist_file() 将参数传递给__gitcomp_nl(),其中 第一个是类似的列表:

      abc def/Z
      foo bar.txt Z
      

      其中ZEOL 的标记。

      • __git ls-tree | sed 中 blob 的尾随空格。
        使得补全结果变成:

        git show HEAD:foo\ bar.txt\ <CURSOR>
        

      因此,Git 将尝试查找名为“foo bar.txt”的文件。

      • __git ls-tree | sed 中树的尾部斜线。
        它使得 zsh 上的补全结果变成:

        git show HEAD:abc\ def/ <CURSOR>
        

      所以命令 like 上的最后一个空格应该在 zsh 上删除以完成 'abc def/' 下的文件名。

      【讨论】: