skip to Main Content

For some reasons, I need to move from os.system to subprocess.run to concatenate files (can be ASCII files but also binary ones).

While it works fine under Windows (anaconda), the following snippet seems blocked or waiting for something under Linux (Ubuntu): what am I missing?

Note a.txt and b.txt just contain a single (ascii) word.

import os, subprocess
Path = os.getcwd()
bottomFile = 'b.txt'
topFile = 'a.txt'
resultFile = 'c.txt'
    
command_line = f"cat {Path}/{topFile} {Path}/{bottomFile} > {Path}/{resultFile}"
args = command_line.split()
subprocess.run(args, shell = True)

2

Answers


  1. When you use subprocess.run() with shell=True, the argument should be a single string with the full command line, which then gets interpreted by the shell.

    Simply change your run() call to this and it all works on both Linux and Windows:

    subprocess.run(command_line, shell = True)
    

    It’s when you call run() with shell=False that you need to split the command line into the program and its arguments.

    Relevant Documentation

    Ref: https://docs.python.org/3/library/subprocess.html

    Search for shell=True on the page: under subprocess.Popen (which run() calls) there is a description of what that does, and how it differs between Windows and Linux.

    Login or Signup to reply.
  2. A more efficient and much more secure version of your code would instead look like:

    subprocess.run(
      ['cat', '--', f'{Path}/{topFile}', f'{Path}/{bottomFile}'],
      stdout=open(f'{Path}/{resultFile}', 'w')
    )
    

    Unlike the version with shell=True, this works even if your path or filenames have spaces, and a filename that contains something like $(rm -rf ~) in it won’t cause your home directory to be deleted.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search