5

Background

I use the command dir/s in batch files all the time. But, I am unable to call this using python. NOTE: I am using Python 2.7.3.

Code

import subprocess
subprocess.call(["dir/s"])

Error Message

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    subprocess.call(["dir/s"])
  File "C:\Python27\lib\subprocess.py", line 493, in call
    return Popen(*popenargs, **kwargs).wait()
  File "C:\Python27\lib\subprocess.py", line 679, in __init__
    errread, errwrite)
  File "C:\Python27\lib\subprocess.py", line 896, in _execute_child
    startupinfo)
WindowsError: [Error 2] The system cannot find the file specified

I have tried changing the quotations but nothing has worked.

How would I call the dir/s module using subprocess?

xxmbabanexx
  • 8,256
  • 16
  • 40
  • 60

5 Answers5

7

How about

subprocess.call("dir/s", shell=True)

Not verified.

zzk
  • 1,347
  • 9
  • 15
  • 5
    Don't use `shell=True` if you don't need to - `subprocess.call(["cmd", "/c", "dir", "/s"])` is better. – Piotr Dobrogost Mar 04 '13 at 18:27
  • @Piotr Dobrogost why is that better? Sure, this is a simple example, but in general isn't it best to write a single string formatted like the shell expects? – tdelaney Mar 04 '13 at 18:52
  • 2
    @tdelaney because shell=True is in general not so secure as shell=False. "Invoking the system shell with shell=True can be a security hazard if combined with untrusted input. " – zzk Mar 04 '13 at 18:54
  • @zzk When I run the code, it simply returns `0`, without printing the directory. What is the reason for this. – xxmbabanexx Mar 04 '13 at 21:19
  • @xxmbabanexx replace "call" with "check_output" – zzk Mar 04 '13 at 21:32
  • @zzk How would I get the directories for the `D:\\` Drive? Also, why did the original code return `0`? Lastly, what is the difference between `call` and `check_output`? Thanks for your help! – xxmbabanexx Mar 04 '13 at 21:38
  • @zzk why does that freeze my computer? – xxmbabanexx Mar 05 '13 at 00:11
3

This is a lot different than what you're asking but it solves the same problem. Additionally, it solves it in a pythonic, multiplatform way:

import fnmatch
import os

def recglob(directory, ext):
    l = []
    for root, dirnames, filenames in os.walk(directory):
        for filename in fnmatch.filter(filenames, ext):
            l.append(os.path.join(root, filename))
    return l
martineau
  • 119,623
  • 25
  • 170
  • 301
carlosdc
  • 12,022
  • 4
  • 45
  • 62
  • When I did this, the error message told me that `directory` was not defined. I am also assuming that `ext` wouldn't work either. Sorry for being such a n00b, but could you please write the entire thing? – xxmbabanexx Mar 04 '13 at 17:42
  • You need to invoke this function with 2 arguments - directory path and the extension for the files you need to glob. Example: `recglob('C:\foo\bar', '.baz')` – Tuxdude Mar 04 '13 at 17:44
  • @Tuxdude How do I get the global name `fnmatch` to work? Also, could I get a listing of all of my files by doing `".*"`? Would that be possible in any way what-so-ever? Thank you *so* much for the help. – xxmbabanexx Mar 04 '13 at 17:56
  • 1
    @xxmbabanexx: Add an `import fnmatch` at the beginning of the script. Likewise you'll also need another line with `import os`. – martineau Mar 04 '13 at 18:01
  • @martineau I thought that `import os` was outdated. I know that there are exceptions. Is this one of them? – xxmbabanexx Mar 05 '13 at 00:12
  • @xxmbabanexx: Not exactly sure what you mean by "outdated". I only mentioned it because you seemed unaware that you'd need to `import fnmatch` in order to use it and the same logic applies to `os`'s functions. – martineau Mar 05 '13 at 00:33
  • awesome! that's what i was looking for – Liam Aug 24 '15 at 11:54
1

You need a space between dir and /s. So break it into an array of 2 elements. Also as carlosdoc pointed out, you would need to add shell=True, since the dir command is a shell builtin.

import subprocess
subprocess.call(["dir", "/s"], shell=True)

But if you're trying to get a directory listing, make it OS independent by using the functions available in the os module such as os.listdir(), os.chdir()

Tuxdude
  • 47,485
  • 15
  • 109
  • 110
1

I finally found the answer. To list all directories in a directory (e.g. D:\\, C:\\) on needs to first import the os module.

import os

Then, they need to say that they want to list everything. Within that, they need to make sure that the output is printed.

for top, dirs, files in os.walk('D:\\'):
    for nm in files:       
        print os.path.join(top, nm)

That was how I was able to solve it. Thanks to this.

Community
  • 1
  • 1
xxmbabanexx
  • 8,256
  • 16
  • 40
  • 60
-1

As it's an inbuilt part of the command line you need to run it as:

import subprocess
subprocess.call("cmd /c dir /s")
George
  • 1,036
  • 2
  • 11
  • 23
  • 1
    Not even close! You are trying to run a shell command, but using the non-shell list syntax and leaving shell=False. – tdelaney Mar 04 '13 at 18:04
  • 1
    @tdelaney: Actually is fairly close and will work if changed slightly to `subprocess.call(["cmd", "/c", "dir", "/s"])`. – martineau Mar 04 '13 at 18:21
  • 1
    @martineau - there is a huge difference between calling a program directly (use a list) and calling it through a shell (use a string and set shell=True). Subprocess trips a lot of people up... but maybe I did bark a bit loud. Your hybrid (call the shell explicitly instead of shell=True) has me scratching my head too! I think I'd prefer subprocess.call("dir /s", shell=True, stdout=subprocess.PIPE) as the example. – tdelaney Mar 04 '13 at 18:48
  • 1
    @tdelaney: I didn't say it was an optimal approach, only that with a minor change that it would work. I beginning to wonder if maybe you just tend to exaggerate things, because AFAIK there's not much difference between using `shell=True` and calling it yourself, as it gets called either way -- although I suppose some might consider the former arguably more explicit. – martineau Mar 04 '13 at 20:32
  • This also works for me so I'm unsure why it didn't work for some people. I think shell=True isn't required because it's explicitly calling cmd as part of the command - though that may be the better way to write it. – George Dec 14 '16 at 18:20