【问题标题】:Escaping characters in glob patterns in Git在 Git 中转义 glob 模式中的字符
【发布时间】:2014-01-08 10:07:05
【问题描述】:

以下 git 命令(删除所有以 ~ 结尾的文件)使用转义字符

git rm \*~

理由是 git 除了 shell 使用的扩展外,还使用它自己的文件名扩展。

这是否意味着转义字符是一种抑制由 shell 完成的文件名扩展的方法?

不知何故,我无法正确处理这个问题。

  • 为什么 git 使用它自己的文件名扩展?是不是因为 shell 文件名扩展可以在不同的 shell/OS 中以不同的方式工作
  • 如果是这样,为什么不在 git 命令的 shell 级别禁止文件名扩展,并允许 git 使用 glob 模式执行它自己的语义

【问题讨论】:

    标签: git shell


    【解决方案1】:

    是的,转义字符会抑制通常由 Unix shell 执行的文件名扩展。回答子问题:

    1. git rm 可能会实现自己的扩展,因为文件可能不存在于签出目录中。 (想想你先rm *~的情况,然后记住你还想从git中删除它们。)

    2. 使用反斜杠转义字符(或将参数括在引号中)正是这样做的——在 shell 级别抑制文件名扩展。这不能由git 自动完成,因为git 不控制你的shell,当它执行时,扩展已经结束。扩展必须由 shell 本身来防止,或者更实际地,由最终用户通过 shell 调用 git 来防止。

    【讨论】:

    • 这是正确的,但缺少 git 扩展 glob 方式的实际差异。是的,shell 不会将 glob 扩展到它无权访问的文件,但它在设计上特别不是递归的。如果您希望 shell 将 glob 扩展为子目录中的文件,您必须明确说明它(例如,*/*)。 git 文件名扩展默认是递归的,如果你希望它不扩展为子目录中的文件,你必须明确说明它(例如,/*)。见my answer
    • @DeNovo 好点,我在写这个答案时不知道 git globbing 的递归行为。
    【解决方案2】:

    为什么 git 使用自己的文件名扩展?

    @user4815162342 的答案缺少从 shell 中转义 glob 元字符(例如 *)的关键原因:

    git 的文件名扩展是递归的。你的shell的文件名扩展不是。确认:

    mkdir testA testA/testB
    cd testA
    touch test1.txt testB/test2.txt
    git init
    

    现在你有了一个目录结构和 git repo 来测试递归文件名扩展。在 testA 中:

    echo *.txt
    # test1.txt
    git add \*.txt
    git status
    # On branch master
    #
    # No commits yest
    #
    # Changes to be committed:
    #   (use "git rm --cached <file>..." to unstage)
    #
    # new file:    test1.txt
    # new file:    testB/test2.txt
    

    您可以看到,shell 的文件名扩展不是递归的,因为echo *.txt 仅扩展为testA 目录中的文本文件。如果您运行了git add *.txt,您将只添加test1.txt。另一方面,git 中的文件名扩展是递归的。当您运行 git add \*.txt,从 shell 中抑制 glob 元字符并允许 git 扩展它时,它会扩展到您的 repo 中的所有 .txt 文件,其中包括子目录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      相关资源
      最近更新 更多