0
import subprocess

subprocess.call('ls', shell=True)

Output:

'ls' is not recognized as an internal or external command, operable program or batch file.
tripleee
  • 175,061
  • 34
  • 275
  • 318
Surya
  • 37
  • 1
  • 3
  • `ls` is not a command on windows. If you want to use linux commands on windows, use WSL or Cygwin. – SuperStormer Apr 07 '20 at 22:57
  • What do you expect `ls` to do on Windows? It currently behaves the same as if you typed it into `cmd.exe`? Are you trying to run a Powershell alias? Or a Unix command? – that other guy Apr 07 '20 at 22:58
  • 1
    For portability and efficiency reasons you should avoid running external commands when there are Python standard modules offering the same functionalities. In this case you can call `os.scandir` to get directory listings and file information. – blhsing Apr 07 '20 at 23:02

2 Answers2

2

ls is not a Windows command. It works on Unixes. Its counterpart on Windows is dir. Try iy out:

import subprocess
subprocess.call('dir', shell=True)

If, for some arcane reason, you have to call ls there is a bunch of ways to do so.

Firstly, Windows PowerShell supports calling ls, you just have to tell Python to execute it (the path below is valid on my system):

subprocess.call(r'c:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe ls', shell=True)

Alternatively, Windows 10 now supports an interoperability layer between Windows and Linux, which allows to use Linux's environment on Windows (called Windows Subsystem for Linux). If you have it installed, one of the way to use it is to precede Linux command with wsl:

subprocess.call('wsl ls', shell=True)

Lastly, the most universal way to list the directory would involve using the built-in Python functionality. E.g the following would give you the content of the current directory:

import os
os.listdir('.')
lukeg
  • 4,189
  • 3
  • 19
  • 40
1

If your goal is to run (Git) Bash on Windows as your shell for subprocess.run() and friends, you'll need to pass in an executable= keyword argument to point to its location.

import subprocess

listing = subprocess.check_output(
    'ls', shell=True, executable='c:/Program Files (x86)/Git/bin/bash.exe')

(where obviously you will need to make sure the file name is correct; I'm guessing wildly here).

As an aside, you should generally avoid ls in scripts. Python has good facilities for getting information about file size, ownership, etc via the pathlib module, or look in the os module if you need to support really old versions of Python (and of course glob.glob() for wildcard expansion, though ls is useless for that too).

On Linux (or Unix-like platforms generally) this is also necessary if you want to use Bash-specific shell syntax like arrays, process substitution, brace expansion, here strings, etc etc etc. The location of Bash is often /bin/bash for the system-installed version, though it's not entirely uncommon to have it in /usr/bin/bash, or somewhere like /usr/local/bin/bash or somewhere in /opt for a custom-installed version.

p = subprocess.run(
    # Need bash for '{...}' and '<<<'
    'cat /tmp/{one,two} - <<<"three"',
    shell=True, executable='/bin/bash',
    capture_output=True, check=True)

For merely running a single executable, you usually want to avoid shell=True though you'll need to specify the full path to the executable if it's not on your PATH.

subprocess.call(['/bin/ls'])

(where obviously with Git Bash on Windows, the actual directory where ls.exe is installed will be something a lot longer and more godforsaken).

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • https://stackoverflow.com/a/39819465/874188 has some caveats related to 32-bit vs 64-bit Windows binaries. – tripleee Sep 11 '21 at 11:10