为什么 `$(gitbranch)` 输出文件夹内的所有文件名(除了 gitbranch)?

Gab*_*goc 11 command-line bash git

我写了一个命令来删除所有 git 分支,而不需要手动全部写入,目前是这样的:

git branch -d $(git branch)
Run Code Online (Sandbox Code Playgroud)

它执行我想要的操作,但还尝试删除当前目录中名为文件的分支,因此输出如下所示:

error: branch 'angular.json' not found.
error: branch 'assembly.xml' not found.
error: branch 'ci-settings.xml' not found.
error: branch 'coverage' not found.
error: branch 'cypress.json' not found.
error: branch 'Dockerfile.angular' not found.
error: branch 'Dockerfile.spring' not found.
error: branch 'e2e' not found.
error: branch 'examples' not found.
error: branch 'mvnw' not found.
error: branch 'mvnw.cmd' not found.
error: branch 'nginx' not found.
error: branch 'node' not found.
error: branch 'node_modules' not found.
error: branch 'package.json' not found.
error: branch 'package-lock.json' not found.
error: branch 'pom.xml' not found.
error: branch 'README.md' not found.
error: branch 'scripts' not found.
error: branch 'serve-proxy.conf.json' not found.
error: branch 'src' not found.
error: branch 'target' not found.
error: branch 'to-do.txt' not found.
error: branch 'tsconfig.json' not found.
error: branch 'web.config' not found.
error: Cannot delete branch 'dev' checked out at 'D:/Documentos/oreons/Rise/archivekeeper-ui'
Deleted branch test (was 729628a).
Run Code Online (Sandbox Code Playgroud)

如果我 echo $(git branch),输出如下:

$ echo $(git branch)
angular.json assembly.xml ci-settings.xml coverage cypress.json Dockerfile.angular Dockerfile.spring e2e examples mvnw mvnw.cmd nginx node node_modules package.json package-lock.json pom.xml README.md scripts serve-proxy.conf.json src target to-do.txt tsconfig.json web.config dev
Run Code Online (Sandbox Code Playgroud)

这解释了命令的输出。但是为什么$(git branch)除了 git 分支之外还输出所有这些文件名呢?

Dan*_*Dan 19

正如@steeldriver在上面的评论中提到的,在其输出中git branch有一个星号(*)来标记当前签出的分支。

$ git branch
* main
  test
Run Code Online (Sandbox Code Playgroud)

当运行它时$(git branch),输出中的星号将扩展到您当前所在目录中的所有非隐藏文件和目录。

要删除星号,您可以--format通过仅显示引用名称的短格式来传递选项来格式化输出。

$ git branch --format='%(refname:short)'
main
test
Run Code Online (Sandbox Code Playgroud)

所以您要使用的命令如下。

git branch -d $(git branch --format='%(refname:short)')
Run Code Online (Sandbox Code Playgroud)


kni*_*ttl 7

不要git branch在脚本中使用。相反,请使用低级命令,例如git for-each-ref

\n
git for-each-ref --shell --format=\'%(refname:short)\' refs/heads | \\\nwhile read branch; do git branch -d "$branch"; done\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
git for-each-ref --shell --format=\'%(refname:short)\' refs/heads | \\\nxargs git branch -d\n
Run Code Online (Sandbox Code Playgroud)\n

这避免了问题中的命令问题,因为它正确地引用了参数扩展。不引用参数扩展(或命令替换)将对扩展值执行路径名扩展。

\n

由于git branch是面向用户的命令,因此它用*. 您可能知道,*作为通配符/通配符,它​​解析为任意 0 个或多个字符。执行时echo *,您的 shell 首先扩展并替换*当前目录中的所有(非隐藏)文件,然后将此文件列表作为参数传递给echo.

\n

结论:总是引用“美元表达式”(不是真正的术语,我说的是参数扩展命令替换)以防止字段分割和路径名扩展 \xe2\x80\x93 除非你有充分的理由不这样做(并且知道你在做什么)

\n

  • @jwodder 我不同意投反对票。`git Branch` 内部使用 `git for-each-ref`,而 `for-each-ref` 在脚本中使用更好、更安全。我的答案直接回答了OP的问题,但这个答案作为“永久”解决方案更正确。 (3认同)