1

I have a .py file in the home directory which contains these three lines:

 import os

 os.system("cd Desktop/")
 os.system("ls")

and I want it to "ls" from the "Desktop" directory but it shows contents of the /home directory.
I looked at these pages:
Calling an external command in Python
http://ubuntuforums.org/showthread.php?t=729192
but I could not understand what to do. Can anybody help me?

Community
  • 1
  • 1
Haj Nasser
  • 304
  • 2
  • 14
  • try os.system("ls Desktop/") – gustavgans Nov 09 '15 at 15:17
  • 4
    Is there a reason you need to use external processes, vs. `os.chdir` and `os.listdir`? – ShadowRanger Nov 09 '15 at 15:17
  • 1
    Possible duplicate of [Shell - Multiple commands in one line](http://stackoverflow.com/questions/5130847/shell-multiple-commands-in-one-line) – Emilien Nov 09 '15 at 15:18
  • Also, side-note: If you _do_ need to run external processes, `os.system` is slower/less secure/less flexible than using the various `subprocess` functions. `os.system` launches all commands in a subshell (which introduces possible reliability and security issues with argument parsing, shell metacharacters, etc.), where something like `subprocess.check_call` with a `list` of the command and arguments is both faster and safer. – ShadowRanger Nov 09 '15 at 15:21
  • Possible duplicate of [How do I "cd" in python](http://stackoverflow.com/questions/431684/how-do-i-cd-in-python) – Remi Guan Nov 10 '15 at 01:37

2 Answers2

1

The two calls are separate from each other. There is no context kept between successive invocations of os.system because a new shell is spawned for every call. First os.system("cd Desktop/") switches directories to Desktop and exits. Then a new shell executes ls in the original folder.

Try chaining your commands with &&:

import os

os.system("cd Desktop/ && ls")

This will show the contents of directory Desktop.


Fabric

If your application is going to be heavy on os usage you might consider using python-fabric. It allows you to use higher level language constructs like contextmanagers to make command line invocations easier:

from fabric.operations import local
from fabric.context_managers import lcd

with lcd("Desktop/"): # Prefixes all commands with `cd Desktop && `
    contents=local("ls", capture=True)
Sebastian Wozny
  • 16,943
  • 7
  • 52
  • 69
  • 1
    To be clear, the reason this happens when you use separate `os.system` invocations is that each `os.system` spawns a new shell to run the commands. So the new shell changes directories, then exits. Then a whole new shell is spawned (in the original directory, not the changed one) and runs. – ShadowRanger Nov 09 '15 at 15:18
  • "ls Desktop/" would be shorter ;) – gustavgans Nov 09 '15 at 15:18
0

You have to consider that os.system executes the commands in a sub-shell. Hence 1) python starts a sub-shell, 2) the directory is changed, 3) then the sub-shell is completed, 4) return to previous state.

To force the current directory change you should do:

os.chdir("Desktop")

Always try and do it by other means that through os.system (os.listdir), or also by doing other than subprocess (which is an excellent module for command control in the shell)

nickpapior
  • 752
  • 1
  • 8
  • 14