Error in check_call() subprocess, executing 'mv' unix command: "Syntax error: '(' unexpected"
Error in check_call() subprocess, executing 'mv' unix command: "Syntax error: '(' unexpected"
我正在为 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)
...
当 Travis building 达到那条线时,我收到一个错误:
/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
。如果我在 Linux shell 上执行此命令,我会瞄准但不是通过 check_call() 命令。
注意:我不能一个一个的移动文件,因为还有很多
我不知道 Travis 默认使用哪个 shell 因为我没有指定它,我只知道如果我在我的 .travis.yml:[=23 中写命令=]
.travis.yml
...
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?
subprocess.something
方法的参数必须是命令行参数列表。使用例如shlex.split()
将字符串拆分为正确的命令行参数:
import shlex, subprocess
subprocess.check_call( shlex.split("mv !(...)") )
编辑:
因此,目标是移动 files/directories,但某些文件/目录除外。通过玩弄 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)
并且它应该按照您的预期进行。
让我再试一次:shell 您希望您的语法 !(...)
能在其中工作吗?是bash吗?是ksh吗?我从未使用过它,快速搜索相应的 bash 功能也无济于事。我怀疑您的语法只是 错误 ,这就是错误消息告诉您的内容。在那种情况下,您的问题完全独立于 python 和 subprocess
模块。
如果您的系统上有一个特殊的 shell 支持此语法,您需要确保 Python 在调用您的命令时使用相同的 shell。它会告诉您它一直在使用哪个 shell:/bin/sh
。这通常只是 link 到真正的 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:
$ !(uname)
Linux
您正在使用 bash 功能 extglob
来尝试排除您指定的文件。您需要启用它才能排除您指定的两个条目。
python 子进程模块在您使用 shell=True
时显式使用 /bin/sh
, 不会 启用 [=28] =] 默认情况下这样的功能(使它更像原始 sh
是合规性的事情)。
如果你想得到bash解释命令;您必须明确地将其传递给 bash,例如使用:
subprocess.check_call(["bash", "-O", "extglob", "-c", "mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder"])
不过,我不会选择以这种方式完成工作。
我正在为 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)
...
当 Travis building 达到那条线时,我收到一个错误:
/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
。如果我在 Linux shell 上执行此命令,我会瞄准但不是通过 check_call() 命令。
注意:我不能一个一个的移动文件,因为还有很多
我不知道 Travis 默认使用哪个 shell 因为我没有指定它,我只知道如果我在我的 .travis.yml:[=23 中写命令=]
.travis.yml
...
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?
subprocess.something
方法的参数必须是命令行参数列表。使用例如shlex.split()
将字符串拆分为正确的命令行参数:
import shlex, subprocess
subprocess.check_call( shlex.split("mv !(...)") )
编辑: 因此,目标是移动 files/directories,但某些文件/目录除外。通过玩弄 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)
并且它应该按照您的预期进行。
让我再试一次:shell 您希望您的语法 !(...)
能在其中工作吗?是bash吗?是ksh吗?我从未使用过它,快速搜索相应的 bash 功能也无济于事。我怀疑您的语法只是 错误 ,这就是错误消息告诉您的内容。在那种情况下,您的问题完全独立于 python 和 subprocess
模块。
如果您的系统上有一个特殊的 shell 支持此语法,您需要确保 Python 在调用您的命令时使用相同的 shell。它会告诉您它一直在使用哪个 shell:/bin/sh
。这通常只是 link 到真正的 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:
$ !(uname)
Linux
您正在使用 bash 功能 extglob
来尝试排除您指定的文件。您需要启用它才能排除您指定的两个条目。
python 子进程模块在您使用 shell=True
时显式使用 /bin/sh
, 不会 启用 [=28] =] 默认情况下这样的功能(使它更像原始 sh
是合规性的事情)。
如果你想得到bash解释命令;您必须明确地将其传递给 bash,例如使用:
subprocess.check_call(["bash", "-O", "extglob", "-c", "mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder"])
不过,我不会选择以这种方式完成工作。