28

Assuming I define a trivial task to list files on a remote server:

from fabric.api import run, env

env.use_ssh_config = True

def list_files():
    run('ls')

And I execute it with:

fab -H server list_files

How can I specify the working directory for the command I'm running, other than doing:

run('cd /tmp && ls')

Which doesn't look very idiomatic to me?

Disclaimer: I'm looking at Fabric for the first time in my life and I'm totally new to Python.

Roberto Aloi
  • 30,570
  • 21
  • 75
  • 112
  • 1
    be sure you take a look at the [tutorial](http://docs.fabfile.org/en/1.4.1/tutorial.html), this very question is covered in there. – Morgan Apr 23 '12 at 17:07

2 Answers2

49

Use the Context Manager cd:

from fabric.api import run, env
from fabric.context_managers import cd

env.use_ssh_config = True

def list_files():
    with cd('/tmp'):
        run('ls')
Daniel Hepper
  • 28,981
  • 10
  • 72
  • 75
  • 1
    But what if I want **all** of my `run` commands to run in the same directory? Will I have to wrap my entire fabfile in a `with cd()`? Is there not something like `env.working_dir = '/my/dir'`? – Dotl Oct 18 '17 at 10:04
  • @Dotl if you don't want a huge block wrapped in a context manager, put all the black into a separate function and wrap call to this function into the context manager. – warvariuc Mar 16 '18 at 12:43
  • 2
    Note that the `Context` object now is contained within [Invoke](http://docs.pyinvoke.org/en/latest/api/context.html#invoke.context.Context.cd) – Juddling Jun 19 '18 at 21:26
23

Answer for fabric 2.4.0 looks like this:

from fabric import Connection

conn = Connection(host=HOST_NAME, user=USER_NAME, connect_kwargs={'password': PASSWORD})

with conn.cd('/tmp/'):
    conn.run('ls -la')

This is not covered by the fabric documentation but by the invoke documentation.

Roman
  • 774
  • 7
  • 12
  • The fabric documentation suggests doing `with Connection('host') as c:`, so would you nest the with statements inside of each other? `with Connection('host') as c: with c.cd('/tmp/'):` – Colin B Jul 31 '20 at 23:13