Basic cygwin commands from python subprocess

Question:

I want to run cygwin from python and execute cygwin commands.

I am using Windows, so I want to run commands in cygwin not cmd. I am using Python 3.6.1.

I just want to know how to run basic commands so I can work from there like ls. I have tried:

  • subprocess.call("E:/cygwin/bin/bash.exe", "ls") (something like this, but it does not work)
  • the solution below suggested by @pstatix, which uses Popen(). Running stdin.close() after stdin.write(b’ls’) results in a /usr/bin/bash: line 1: ls: command not found error

I am able to do the following:

  • open cygwin: subprocess.call("E:/cygwin/bin/bash.exe")

  • (run commmands on Windows cmd: subprocess.call("dir", shell=True))

Is this possible in this format?
Does cygwin automatically close when I run the next python command, or do I need to exit before that?

I am relatively new to this.

Asked By: sandboxj

||

Answers:

from subprocess import Popen, PIPE

p = Popen("E:/cygwin/bin/bash.exe", stdin=PIPE, stdout=PIPE)
p.stdin.write("ls")
p.stdin.close()
out = p.stdout.read()
print (out)
Answered By: pstatix
from subprocess import Popen, PIPE, STDOUT

p = Popen(['E:/cygwin/bin/bash.exe', '-c', '. /etc/profile; ls'], 
          stdout=PIPE, stderr=STDOUT)
print(p.communicate()[0]))

This will open bash, execute the commands provided after -c and exit.

You need the prepended . /etc/profile; because bash is beeing started in a non-interactive mode, thus none of the environment variables are intialized and you need to source them yourself.

If you have cygwin installed over the babun software in your user folder (like I have) the code looks like this:

from subprocess import Popen, PIPE, STDOUT
from os.path import expandvars

p = Popen([expandvars('%userprofile%/.babun/cygwin/bin/bash.exe'), '-c', '. /etc/profile; ls'], 
          stdout=PIPE, stderr=STDOUT)
print(p.communicate()[0])
Answered By: MadMike

For me the sollution mentioned above were giving issues like :
p.stdin.write("ls")
Traceback (most recent call last):
File "", line 1, in
TypeError: a bytes-like object is required, not ‘str’

I fixed it with command sent in byte format

    from subprocess import Popen, PIPE
    p = Popen(r"C:/cygwin64/bin/bash.exe", stdin=PIPE, stdout=PIPE)
    p.stdin.write(b"ls")
    p.stdin.close()
    out = p.stdout.read()
    print(out)
Answered By: Avinash Kumar Jha
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.