Search code examples
pythonbashsubprocessspecial-charactersfile-not-found

python subprocess module can't parse filename with special characters "("


I have a Python program that reads files and then tars them into tar balls of a certain size.

One of my files not only has spaces in it but also contains parentheses. I have the following code:

cmd = "/bin/tar -cvf " +  tmpname +  " '" + filename + "'"

NOTE: Those are single quotes inside double quotes outside of the filename variable. It's a little difficult to see.

Where tmpname and filename are variables in a for-loop that are subject to change each iteration (irrelevant).

As you can see the filename I'm tarballing contains single quotes around the file name so that the shell (bash) interprets it literally as is and doesn't try to do variable substitution which "" will do or program execution which ` will do.

As far as I can see, the cmd variable contains the exact syntax for the shell to interpret the command as I want it to. However when I run the following subprocess command substituting the cmd variable:

cmdobj = call(cmd, shell=True)

I get the following output/error:

/bin/tar: 237-r Property Transport Request (PTR) 012314.pdf: Cannot stat: No such file or directory

/bin/tar: Exiting with failure status due to previous errors

unable to tar: 237-r Property Transport Request (PTR) 012314.pdf

I even print the command out to the console before running the subprocess command to see what it will look when running in the shell and it's:

cmd: /bin/tar -cvf tempname0.tar '237-r Property Transport Request (PTR) 012314.pdf'

When I run the above command in the shell as is it works just fine. Not really sure what's going on here. Help please!


Solution

  • Pass a list of args without shell=True and the full path to the file if running from a different directory:

    from subprocess import check_call
    
    check_call(["tar","-cvf",tmpname ,"Property Transport Request (PTR) 012314.pdf"])
    

    Also use tar not 'bin/tar'. check_call will raise a CalledProcessError if the command returns a non-zero exit status.