我正在为Travis CI制作一个python脚本。
.travis.yml
...
script:
- support/travis-build.py
...
python文件travis-build.py
是这样的:
#!/usr/bin/env python
from subprocess import check_call
...
check_call(r"mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder", shell=True)
...
当特拉维斯大楼达到那条线时,我收到了一个错误:
/bin/sh: 1: Syntax error: "(" unexpected
我只是尝试了很多不同的形式来编写它,但我得到了相同的结果。有什么想法吗?
提前致谢!
修改
我当前的目录布局:
- my_project/final_folder/
- cmake-3.0.2-Darwin64-universal/
- fileA
- fileB
- fileC
我正在尝试使用此命令将所有当前文件fileA
,fileB
和fileC
移至my_project
和cmake-3.0.2-Darwin64-universal
文件夹中除./my_project/final_folder
和...
script:
# Here is the previous Travis code
- mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder
...
个文件夹1}}。如果我在Linux shell上执行此命令,我会得到我的目标,但不是通过check_call()命令。
注意:我无法逐个移动文件,因为还有很多其他文件
我不知道Travis默认使用哪个shell,因为我没有指定它,我只知道如果我在.travis.yml中编写命令:
.travis.yml
{{1}}
有效。但如果我使用该脚本,则会失败。
我从以下问题中找到了这个命令:
How to use 'mv' command to move files except those in a specific directory?
答案 0 :(得分:2)
您正在使用 bash 功能extglob
,尝试排除您指定的文件。您需要启用它才能将其排除在您指定的两个条目之外。
当您使用/bin/sh
时,python子进程模块明确使用shell=True
,不默认情况下允许使用这样的bash功能(&#39) ;遵守法律使其更像原始sh
)。
如果你想让bash解释命令;你必须明确地将它传递给bash,例如使用:
subprocess.check_call(["bash", "-O", "extglob", "-c", "mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder"])
但是,我不会选择以这种方式完成工作。
答案 1 :(得分:0)
让我再试一次:你期望在哪个shell中使用语法!(...)
?是bash吗?是ksh吗?我从来没有使用它,快速搜索相应的bash功能无处可去。我怀疑你的语法只是错误,这是错误信息告诉你的。在这种情况下,您的问题完全独立于python和subprocess
模块。
如果系统上的特殊shell支持此语法,则需要确保在调用命令时Python使用相同的shell。它告诉你它使用了哪个shell:/bin/sh
。这通常只是真正的shell可执行文件的链接。它是否指向您测试命令的同一个shell?
编辑:您引用的SO解决方案包含注释中的解决方案:
提示:请注意,使用此模式依赖于 extglob 。您可以 使用shopt -s extglob启用它(如果你想扩展globs 默认情况下你可以将shopt -s extglob添加到.bashrc)
只是为了证明不同的shell可能以不同的方式处理你的语法,首先使用bash:
$ !(uname)
-bash: !: event not found
然后,使用/ bin / dash:
$ !(uname)
Linux
答案 2 :(得分:-1)
subprocess.something
方法的参数必须是命令行参数列表。使用例如shlex.split()
使字符串被拆分为正确的命令行参数:
import shlex, subprocess
subprocess.check_call( shlex.split("mv !(...)") )
编辑: 因此,目标是移动文件/目录,同时免除某些文件/目录(ies)。通过玩bash,我可以让它像这样工作:
mv `ls | grep -v -e '\(exclusion1\|exclusion2\)'` my_project
所以在你的情况下:
mv `ls | grep -v -e '\(myproject\|cmake-3.0.2-Darwin64-universal\)'` my_project
这可以进入subprocess.check_call(..., shell=True)
,它应该按照您的预期进行。