2

How do I append to a file without opening it using Linux echo command? I've tried all sort of possibilities but unable to achieve the result. I'm not sure what I'm missing.

Documentation said to type out the exact command when shell is set to 'True' (Yes with security risk). The echo command works when I type it in Linux terminal but not through subprocess. I don't see the "test.txt" with 'This is a test string.'

>>> string = 'This is a test string.'    
>>> cmd = 'echo \"' + string + '\" >> test.txt'
>>> cmd
'echo "This is a test string." >> test.txt'
>>> 
>>> subprocess.check_call (cmd, shell = True)
0
>>> 
>>> subprocess.call (['echo', '\"', string, '\"', ' >> ', ' test.txt'])
0
>>> 
dreamzboy
  • 795
  • 15
  • 31
  • What do you mean by “without opening it”? You have to open a file to append to it.* – Ry- Jun 19 '15 at 01:38
  • @minitech I suspect he wants to not have to open it in the python process, though it will ultimately be opened by the shell, which is a "subprocess" of the python process. At best this saves having to deal with using the python APIs to open and write to the file. – The Busy Wizard Jun 19 '15 at 02:10
  • You shouldn't see any output, since you are *redirecting* the output to a file. – Joel Cornett Jun 19 '15 at 05:14

2 Answers2

2

As discussed in this answer, when using, shell=True, you should pass a string, not a list, as the first argument. Thus the correct code would be:

subprocess.call('echo "foo" >> bar.txt', shell=True)

Demonstration:

>>> import subprocess
>>> subprocess.call('echo "foo" >> /tmp/bar.txt', shell=True)
0
>>> open('/tmp/bar.txt').read()
'foo\n'
>>>
Community
  • 1
  • 1
Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
  • Is there any way to do this without passing a string with `shell=True`? Something like passing `['echo', ' "append me" ', '>>', 'file.txt']` ? – manesioz Oct 17 '19 at 15:04
  • 1
    @ZacharyManesiotis not as is, `>> file` is a shell operator. You however, can perform the redirect programmatically by using the `stdout=` keyword argument. – Joel Cornett Oct 17 '19 at 15:07
  • This was a huge help, I don't know why I didn't consider that. Thank you! – manesioz Oct 17 '19 at 15:26
-1

You're passing the redirector ">>" as an argument to echo, but it's not an argument, it's part of the shell. You'll need to run the shell with a string for the command. That string would be what's in your cmd variable. The immediate option that comes to mind is:

subprocess.call(["sh", "-c", cmd]);

Though I've rarely used the subprocess module, and that may not be the best way to get what you want.

The Busy Wizard
  • 956
  • 1
  • 7
  • 11
  • 1
    The shell=True argument alleviates the need to run the shell directly – hd1 Jun 19 '15 at 02:22
  • @hd1 It is my understanding that the arguments however, are still passed to the echo command, meaning that the shell does not interpret the ">>", which is why it's not redirecting the output. My answer is tested, and I believe correct. Though as stated, I'm by no means intimately familiar with the subprocess module; I may be wrong. Though the code in my response does work for me, while the OPs code, does not. – The Busy Wizard Jun 19 '15 at 04:56
  • @IanWizard: `shell=True` causes the command to be run as `sh -c ''`, which means that all unescaped shell operators will be correctly interpreted. – Joel Cornett Jun 19 '15 at 05:07
  • @IanWizard, what hd1 and I understand are still correct. The "shell = True" suppose to pass the whole string to shell like what you would type at the terminal. It obviously isn't working probably due to what you mentioned above. Either way, your method works as expected. I'm not sure the " ; " at the end of your code is C-related or a wink. Thank you for the answer. – dreamzboy Jun 19 '15 at 05:15
  • @dreamzboy I'm glad it works for you. After digging deeper it does seem that shell=True should be working, so yeah, it's a little odd that it just doesn't. Also, the semicolon is just part of the code. – The Busy Wizard Jun 19 '15 at 16:51
  • Is there any way to do this without passing a string with `shell=True`? Something like passing `['echo', ' "append me" ', '>>', 'file.txt']` ? – manesioz Oct 17 '19 at 15:04