Reputation: 541
I have a simple script in order to understand how one can run a shell for loop inside a subprocess call. I'm running it from GNU/Linux, inside a virtual enviroment and a BASH shell.
The script:
from subprocess import call
shellCommand = ['for','c','in','$(seq 1 10)','do','echo','$c','done']
call(shellCommand, shell=True)
And the error message:
c: 1: c: Syntax error: Bad for loop variable
What am I doing wrong here?
Upvotes: 0
Views: 126
Reputation: 158898
I'd just do this sort of thing at the Python layer.
# for i in $(seq 10); do ...; done
for i in range(10):
subprocess.call([...])
# for f in *.py; do ...; done
py_files = [f for f in os.listdir('.') where f.endswith('*.py')]
for f in py_files:
subprocess.call([..., f, ...])
If at all possible you should avoid using shell=True
because it is actually dangerous. Consider a filename or user input that contains a ;
or a in it: how do you protect against it not doing what you expect (and how do you protect against a caller running any shell command on behalf of your process)? The array form avoids this problem.
Upvotes: 1
Reputation: 1121824
There are two problems:
The correct syntax is:
for c in $(seq 1 10); do echo $c; done
Note the ;
after the for ... in ...
part before do
, and another one after each command inside the do ... done
block. You could also use newlines:
for c in $(seq 1 10)
do
echo $c
done
Put your whole shell script in one argument; the argument is passed to sh -c ...
and the -c
switch expects the whole script in a single argument value:
shell_command = 'for c in $(seq 1 10); do echo $c; done'
call(shell_command, shell=True)
or, alternatively, using newlines:
shell_command = 'for c in $(seq 1 10)\ndo\n echo $c\ndone'
call(shell_command, shell=True)
or
shell_command = '''
for c in $(seq 1 10)
do
echo $c
done
'''
call(shell_command, shell=True)
Upvotes: 1