简体   繁体   中英

for loop in `Subprocess.run` results in `Syntax error: "do" unexpected`

I'm trying to run a for loop in a shell through python. os.popen runs it fine, but is deprecated on 3.x and I want the stderr. Following the highest-voted answer on How to use for loop in Subprocess.run command results in Syntax error: "do" unexpected , with which shellcheck concurs:

import subprocess
proc = subprocess.run(
    "bash for i in {1..3}; do echo ${i}; done",
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE, )

print(proc.stderr)

I'm ultimately trying to reset all usbs by calling this shell code https://unix.stackexchange.com/a/611305/362437 through python, so any alternate approaches to doing that would be appreciated too.

When you do

subprocess.run('foo', shell=True)

it actually runs the equivalent of

/bin/sh -c 'foo'

(except that it magically gets all quotes right:-) ). So, in your case, it executes

/bin/sh -c "bash for i in {1..3}; do echo ${i}; done"

So the "command" given with the -c switch is actually a list of three commands: bash for i in {1..3} , do echo ${i} , and done . This is going to leave you with a very confused shell.

The easiest way of fixing this is probably to remove that bash from the beginning of the string. That way, the command passed to /bin/sh makes some sense.

If you want to run bash explicitly, you're probably better off using shell=False and using a list for the first argument to preserve your quoting sanity. Something like

import subprocess
proc = subprocess.run(
    ['/bin/bash', '-c', 'for i in {1..3}; do echo ${i}; done'],
    shell=False,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE, )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM