从bash脚本中运行时,flake8的行为有所不同

时间:2018-11-05 21:59:13

标签: bash git flake8

我想这里的答案可能微不足道,但是我可能需要一些复杂的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)

我将不胜感激

1 个答案:

答案 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

但是棘手的提示在突出显示中

screenshot of terminal output

附录

虽然与您的问题无关,但这可能是实现所需目标的更好方法:

$ 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周围的许多粗糙边缘(这样的!)。