我应该如何在 Python 结构中使用 extglob?

How should I use extglob in Python fabric?

我正在尝试使用 fabric (v2.6) 运行 一些使用 bash 的 extglob 和 dotglob 的命令。

当我运行:

c.run(f"shopt -s extglob dotglob && rm -Rf {project_path}* !(.|..|.venv) && shopt -u extglob dotglob")

我收到这个错误:

`bash: -c: line 0: syntax error near unexpected token `('`

我正在使用 &&,因为我发现在单独的 运行 调用中执行 shopt -s extglob dotglob 不会持续用于后续的 运行 调用。我很确定使用 && 会启用 extglob 和 dotglob,因为当我这样做时:

`c.run("shopt -s extglob dotglob && shopt")`

它打印出选项列表并且 extglob 和 dotglob 都已启用。

我哪里错了?

来自the bash wiki

extglob changes the way certain characters are parsed. It is necessary to have a newline (not just a semicolon) between shopt -s extglob and any subsequent commands to use it.

所以您必须适当地更改您的 python 代码,以便使用换行符而不是 &&

或者直接执行 bash 调用在 python 中执行的操作。

不幸的是,extglob 似乎无法与 Python Fabric 一起使用。

来自bash docs

extglob changes the way certain characters are parsed. It is necessary to have a newline (not just a semicolon) between shopt -s extglob and any subsequent commands to use it.

但是从Fabric docs

While Fabric can be used for many shell-script-like tasks, there’s a slightly unintuitive catch: each run [...] has its own distinct shell session. This is required in order for Fabric to reliably figure out, after your command has run, what its standard out/error and return codes were.

幸运的是,可以使用 Bash 的 GLOBIGNORE shell 变量代替

来实现类似的事情

The GLOBIGNORE shell variable may be used to restrict the set of file names matching a pattern. If GLOBIGNORE is set, each matching file name that also matches one of the patterns in GLOBIGNORE is removed from the list of matches. If the nocaseglob option is set, the matching against the patterns in GLOBIGNORE is performed without regard to case. The filenames . and .. are always ignored when GLOBIGNORE is set and not null. However, setting GLOBIGNORE to a non-null value has the effect of enabling the dotglob shell option, so all other filenames beginning with a ‘.’ will match. To get the old behavior of ignoring filenames beginning with a ‘.’, make ‘.*’ one of the patterns in GLOBIGNORE. The dotglob option is disabled when GLOBIGNORE is unset.

扩展通配符时,这也很容易忽略 ...,因此要删除目录中的所有文件(“.venv”除外),我们可以执行

c.run("GLOBIGNORE='.venv'; rm -Rf {project_path}*")