check_call()子进程执行“mv”unix命令时出错:“语法错误:”(“意外”

2024-09-28 23:37:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为Travis CI编写一个python脚本。在

。特拉维斯·伊梅尔

...

script:
  - support/travis-build.py

...

python文件travis-build.py如下所示:

^{pr2}$

当Travis building达到这条线时,我得到一个错误:

/bin/sh: 1: Syntax error: "(" unexpected

我只是尝试了很多不同的形式来写它,但是我得到了相同的结果。有什么想法吗?在

提前谢谢!在

编辑

我当前的目录布局:

- my_project/final_folder/
- cmake-3.0.2-Darwin64-universal/
- fileA
- fileB
- fileC

我试图用这个命令将当前所有的文件fileAfileB和{},不包括my_project和{}文件夹到./my_project/final_folder。如果我在LinuxShell上执行这个命令,我就可以得到我的目标,但不是通过check_call()命令。在

注意:我无法逐个移动文件,因为还有许多其他文件

我不知道默认情况下Travis使用的是哪个shell,因为我没有指定它,我只知道如果我在我的。特拉维斯·伊梅尔公司名称:

。特拉维斯·伊梅尔

...

script:
  # Here is the previous Travis code
  - mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder

...

它起作用了。但是如果我使用脚本,它就失败了。在

我从以下问题中找到这个命令:

How to use 'mv' command to move files except those in a specific directory?


Tags: 文件py命令buildproject脚本cmaketravis
3条回答

您正在使用bash功能extglob,试图排除您指定的文件。您需要启用它才能排除您指定的两个条目。在

python子进程模块在使用shell=True时显式使用/bin/sh,默认情况下,不会启用像这样的bash特性(使其更像原始的sh是一个合规的事情)。在

如果要让bash解释命令,则必须显式地将其传递给bash,例如使用:

subprocess.check_call(["bash", "-O", "extglob", "-c", "mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder"])

不过,我不会选择这样做。在

subprocess.something方法的参数必须是命令行参数的列表。使用例如shlex.split()将字符串拆分为正确的命令行参数:

import shlex, subprocess
subprocess.check_call( shlex.split("mv !(...)") )

编辑: 因此,目标是移动文件/目录,但不包括某些文件/目录。通过使用bash,我可以让它像这样工作:

^{pr2}$

所以你的情况是:

mv `ls | grep -v -e '\(myproject\|cmake-3.0.2-Darwin64-universal\)'` my_project

这可以进入subprocess.check_call(..., shell=True),它应该做你期望它做的事情。在

让我再试一次:您希望您的语法!(...)在哪个shell中工作?是巴什吗?是ksh吗?我从来没有用过它,快速搜索相应的bash特性也没有用过。我怀疑你的语法是错误的,这就是错误信息告诉你的。在这种情况下,您的问题完全独立于python和subprocess模块。在

如果系统上的特殊shell支持此语法,则需要确保Python在调用命令时使用的是同一个shell。它告诉您它一直在使用哪个shell:/bin/sh。这通常只是指向实际shell可执行文件的链接。它是否指向您在其中测试命令的同一个shell?在

编辑:您引用的SO解决方案在注释中包含该解决方案:

Tip: Note however that using this pattern relies on extglob. You can enable it using shopt -s extglob (If you want extended globs to be turned on by default you can add shopt -s extglob to .bashrc)

为了证明不同的shell可能以不同的方式处理语法,首先使用bash:

$ !(uname)
-bash: !: event not found

然后,使用/bin/dash:

^{pr2}$

相关问题 更多 >