I have a python script (e.g. test.py) and a commands.txt file which contains a custom bash function (e.g. my_func) along with its parameters, e.g.
my_func arg1 arv2; my_func arg3 arg4; my_func arg5 arg6;
This function is included in the ~/.bash_profile.
What I have tried to do is:
subprocess.call(['.', path/to/commands.txt], shell=True)
I know this is not the best case, in terms of setting the shell argument into True, but I cannot seem to implement it even in this way. What I get when I run test.py is:
my_func: command not found
2 Answers 2
You will need to invoke bash directly, and instruct it to process both files.
At the command-line, this is:
bash -c '. ~/.bash_profile; . commands.txt'
Wrapping it in python:
subprocess.call(['bash', '-c', '. ~/.bash_profile; . commands.txt'])
You could also source ~/.bash_profile at the top of commands.txt. Then you'd be able to run a single file.
It may make sense to extract the function to a separate file, since .bash_profile is intended to be used by login shells, not like this.
2 Comments
~/.bash_profile.If the first line of your commands.txt file had the correct shebang (for example #!/bin/bash) making your file executable (chmod +x commands.txt) will be enough :
subprocess.call("path/to/commands.txt")
6 Comments
txt doesn't matter?subprocess.call(['chmod +x', ' absolute/path/to/commands.txt'], shell=True) would work as well?
.bash_profile?export -f my_func. If you don't do that then it is only visible to the interactive session you define it in, i.e. it does not get passed to child processes.my_funcuses other bash functions in its definition. Does this affect anything?subprocess.call(['for arg; do . "$arg"; done', '_', os.path.expanduser('~/.bashrc'), '/path/to/commands.txt'], shell=True)will work, if and only if your scripts (commands.txtand.bashrc) are both compatible with/bin/sh.subprocess.Popen(['bash', '-c', 'funcname "$@"', '_'] + args)will be able to run it (withargsbeing a Python list of arguments to pass to the function, ie.args=['foo', 'bar', 'baz']to runfuncname foo bar baz). Usingbashinstead ofshell=Truemakes sure you get a shell that actually knows how to read those exported functions, and passing arguments out-of-band from code is a security precaution: you don't want to pass a freeform field and have someone put$(rm -rf ~)in it.