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

发布于 2025-01-12 11:24:27 字数 632 浏览 2 评论 0原文

我正在尝试使用 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 都已启用。

我这里哪里出错了?

I am trying to use fabric (v2.6) to run some commands that make use of bash's extglob and dotglob.

When I run:

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

I get this error:

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

I am using the && because I found doing shopt -s extglob dotglob in a separate run call doesn't persist for the subsequent run calls. I'm pretty sure using && is enabling extglob and dotglob because when I do this:

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

It prints out the list of options and extglob and dotglob are both enabled.

Where am I going wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烙印 2025-01-19 11:24:27

来自 bash wiki

extglob 改变了某些字符的解析方式。在 shopt -s extglob 和任何后续使用它的命令之间必须有一个换行符(而不仅仅是分号)。

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

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

From 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.

So you have to change your python code appropriately so that a newline is used instead of &&.

Or just do what the bash invocation does directly in python.

荆棘i 2025-01-19 11:24:27

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

来自 bash 文档

extglob 改变了某些字符的解析方式。有必要
shopt -s extglob 和之间有一个换行符不仅仅是分号
使用它的任何后续命令。

但来自 Fabric 文档

虽然 Fabric 可用于许多类似 shell 脚本的任务,但有一个
有点不直观的地方:每个运行 [...]都有其自己独特的 shell 会话。这是必需的
为了让 Fabric 能够可靠地弄清楚,在您的命令执行后
运行,其标准输出/错误和返回代码是什么。

幸运的是,使用 Bash 的 GLOBIGNORE shell 变量也可以实现类似的效果

GLOBIGNORE shell 变量可用于限制文件集
与模式匹配的名称。如果设置了 GLOBIGNORE,则每个匹配文件
与 GLOBIGNORE 中的模式之一匹配的名称将被删除
从比赛列表中。如果设置了 nocaseglob 选项,
与 GLOBIGNORE 中的模式进行匹配无需
视情况而定。文件名 .和 .. 总是被忽略
GLOBIGNORE 已设置且不为空。但是,将 GLOBIGNORE 设置为
非空值具有启用 dotglob shell 选项的效果,因此
以“.”开头的所有其他文件名会匹配。为了得到旧的
忽略以 '.' 开头的文件名的行为,使 '.*' 之一
GLOBIGNORE 中的模式。 dotglob 选项在以下情况下被禁用:
GLOBIGNORE 未设置。

在扩展通配符时,这也可以轻松地忽略 ...,因此要删除目录中的所有文件(除了“.venv”),我们可以这样做

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

It seems extglob can't be used with Python Fabric unfortunately.

From the 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.

But from the 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.

Fortunately, a similar thing can be achieved using Bash's GLOBIGNORE shell variable instead

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.

This also handily ignores . and .. when expanding wildcards, so to remove all files - except '.venv' - in a directory, we can do

c.run("GLOBIGNORE='.venv'; rm -Rf {project_path}*")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文