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?
CodePudding user response:
From the bash wiki:
extglob
changes the way certain characters are parsed. It is necessary to have a newline (not just a semicolon) betweenshopt -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.
CodePudding user response:
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) betweenshopt -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}*")