我想这里的答案可能微不足道,但是我可能需要一些复杂的bash知识。我已经浏览bash文档几个小时了,似乎找不到答案。
我正在研究python存储库,并想出了一个简单的脚本来仅处理当前分支和master之间不同的文件。这是从上述脚本(lint.sh
)中提取的最小工作示例:
#!/bin/bash
paths=$(git diff --name-only -r origin/master...HEAD | grep \.py$)
flake8 $paths
出于测试目的,假设我只提交了一个文件bad.py
,其内容如下:
hello
there
bash lint.sh
的预期输出为:
bad.py:1:1: F821 undefined name 'hello'
bad.py:2:1: F821 undefined name 'there'
但是,输出为空。在调试模式下运行时,bash显示以下命令:
++ git diff --name-only -r origin/master...HEAD
++ grep '.py$'
+ paths='bad.py'
+ flake8 'bad.py'
这是我的期望。另外,当我只运行flake8 bad.py
时,输出就如预期的那样。
我希望此可能与参数传递有关,参数传递在不同的bash版本之间有所不同。 bash --version
的输出:
GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.5.0)
我将不胜感激
答案 0 :(得分:3)
非常抱歉,这并不是一个确切的答案,但肯定不适合发表评论!
给我的提示如下:
+ paths='bad.py'
+ flake8 'bad.py'
在执行同一脚本时,我得到以下信息:
$ bash -x lint.sh
++ git diff --name-only -r origin/master...HEAD
++ grep '.py$'
+ paths=bar.py
+ flake8 bar.py
bar.py:1:1: F821 undefined name 'hello'
bar.py:2:1: F821 undefined name 'world'
在此注意我的输出如何不包含文件名或赋值周围的引号。除非必要,否则bash
通常不会添加引号。这告诉我的是,该字符串中可能有 个控制字符(我的最佳猜测是颜色或\b
+其他字符(这可能是少数情况下的一种)屏幕截图实际上很有帮助!))。
这是我能够重现您的发现的一种方式:
mkdir -p bin
cat > bin/grep << EOF
#!/usr/bin/env bash
exec /bin/grep --color=always "\$@"
EOF
chmod +x bin/grep
# simulate having this `grep` on your path
PATH=$PWD/bin:$PATH bash -x lint.sh
(虽然这似乎很奇怪,但过去我在grep
中放入了自己的~/bin
,所以我可以添加{{1} },现在GREP_OPTIONS
is deprecated-可能会错误地添加--line-buffered --color=auto
并使其正常工作。今天我改为use an alias,因为即使遇到这种情况我也碰到了锋利的边缘。
在这种情况下,输出与您上面的输出匹配:
--color=always
但是棘手的提示在突出显示中
虽然与您的问题无关,但这可能是实现所需目标的更好方法:
$ PATH=$PWD/bin:$PATH bash -x lint.sh
++ git diff --name-only -r origin/master...HEAD
++ grep '.py$'
+ paths='bar.py'
+ flake8 'bar.py'
不同部分的说明:
# if you have GNU xargs
git diff -z --name-only origin/master...HEAD -- '*.py' | xargs --null --no-run-if-empty flake8
# if you need to be more portable (I see you're probably on macos)
git diff -z --name-only origin/master...HEAD -- '*.py' | xargs -0 flake8 /dev/null
:输出以空字节定界的文件名。如果文件名包含空格或其他特殊字符,则可以防止拼接git diff -z
:在扩展参数时将输入分成空字节xargs --null
:如果没有参数(这是GNU扩展名),则根本不要运行可执行文件xargs --no-run-if-empty
:与xargs -0
相同,但是,如果您使用非GNU xargs,则将无法使用长选项。xargs --null
:这是一个偷偷摸摸的技巧,因为bsd xargs没有“如果空则不运行”选项,因此它将始终调用flake8 /dev/null
。如果flake8
用零参数调用,则默认为递归当前工作目录(并整理所有文件)。通过将flake8
放在开头,可以防止此行为,而可以删除一个空文件!附录2,您可能需要考虑使用git hooks框架来为您处理所有这些问题,我维护pre-commit旨在消除/dev/null
周围的许多粗糙边缘(这样的!)。