4

I'm looking for the best way to use bash commands from within python. What ways are there? I know of os.system and subprocess.Popen.

I have tried these:

bootfile = os.system("ls -l /jffs2/a.bin | cut -d '/' -f 4")
print bootfile

This returns a.bin as expected but also it retuns 0 afterwards and so prints:

a.bin
0

with bootfile now being set to 0. The next time I print bootfile it just shows up as 0. Which is the exit value I guess, how do i stop this value interfering?

I have also tried:

bootfile = subprocess.Popen("ls -l /jffs2/a.bin | cut -d '/' -f 4")
print bootfile

but it seems to break the script, as in I get nothing returned at all, have I done that right?

Also which of these is better and why? Are there other ways and what is the preferred way?

5
  • 2
    What is your goal with your bash commands ? I'm sure you could do this in python without calling bash. Commented Feb 28, 2013 at 13:08
  • 1
    Have you considered reading the documentation for subprocess.Popen at all? Commented Feb 28, 2013 at 13:09
  • I wish to return a symlink, this points to the name of the firmware. So in this case I want to return a.bin which will actually point to the name of the actual bin file Commented Feb 28, 2013 at 13:09
  • I am reading it now, I was using an example online and it seems it was terribly wrong. Commented Feb 28, 2013 at 13:10
  • 4
    @Paul so you want os.readlink('/jffs2/a.bin')? Commented Feb 28, 2013 at 13:10

3 Answers 3

3

Using os.readlink (proposed by @kojiro) and os.path.basename for getting only the namefile:

os.path.basename(os.readlink('/jffs2/a.bin'))
Sign up to request clarification or add additional context in comments.

1 Comment

That's perfect thanks, now I want to know why popen returns none and I am satisfied.
2

kojiro's comment about os.readlink is probably what you want. I am explaining what you were trying to implement.

os.system would return you exit status of the command run.

subprocess.Popen will create a pipe, so that you can capture the output of the command run.
Below line will capture output of the command run:

bootfile = subprocess.Popen(["bash","-c","ls -l /jffs2/a.bin | cut -d '/' -f 4"], stdout=subprocess.PIPE).communicate()[0]

More details at http://docs.python.org/library/subprocess.html

3 Comments

That subprocess.Popen command won't work. See the subprocess.Popen docs (in particular the "shell" parameter to Popen()).
thanks that's great, I jsut have to adjust it because instead of returning a.bin, it returns jffs2/a.bin and then none, setting the variable to none then.
I got it to return the binfile now, however it still returns "none" afterwards. You had changed the cut command for some reason :)
1

The right answer, as @kojiro says, is:

os.readlink('/jffs2/a.bin')

But if you really wanted to do this the complicated way, then in Python 2.7:

cmd = "ls -l /jffs2/a.bin | cut -d '/' -f 4"
bootfile = subprocess.check_output(cmd, shell=True)

Or on older Pythons:

cmd = "ls -l /jffs2/a.bin | cut -d '/' -f 4"
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
bootfile = p.communicate()[0]
if p.returncode != 0:
    raise Exception('It failed')

3 Comments

thanks for that, good to know different ways. My problem with popen is bootfile = p.communicate[0] returns both the correct answer and then None after it.
I just fixed a typo... try p.communicate()[0]. (p.communicate() returns a tuple, the [0] bit takes the first element from that tuple).
Hi, I had fixed your typo myself thanks, I should have mentioned that. The thing is, when I am accessing index 0 it is giving me the correct value and none also, then marking the variable as none. Which makes no sense to me. I did it another way but not knowing why bothers me :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.