Search code examples
pythonlinuxshellsubprocessscp

Why does subprocess.call() not execute scp unless "shell=True" is included?


My program securely copies in this manner: subprocess.run(scp -P 22 username@address.com:path/to/file $HOME/Downloads).

But it gives me the following error: FileNotFoundError: [Errno 2] No such file or directory: 'scp -P 22 username@address.com:path/to/file $HOME/Downloads.

However, adding shell=True like so subprocess.run(scp -P 22 username@address.com:path/to/file $HOME/Downloads, shell=True) fixes it.

Why is that? Is there a way around it or is shell=True essential?


Solution

  • If you check the documentation, you'll see that subprocess.run actually wants a list of values, not a single string:

    subprocess.run( ["scp", "-P", "22", 
        "username@address.com:path/to/file"
        "$HOME/Downloads"] )
    

    HOWEVER, there's another issue here. $HOME is a shell variable. If you don't use shell=True, then you need to expand it yourself:

    subprocess.run( ["scp", "-P", "22", 
        "username@address.com:path/to/file",
        os.environ["HOME"]+"/Downloads"] )
    

    You don't need to specify "-P 22". That's the default port for ssh.