This document provides an upgrade path from 1.*
to 2.*
.
There is no sh.cd
command anymore. It was always command implemented in sh, as
some systems provide it as a shell builtin, while others have an actual binary.
But neither of them persisted the directory change between other sh
calls,
which is why it was implemented in sh.
If you were using sh.cd(dir)
, use the context manager with sh.pushd(dir)
instead. All of the commands in the managed context will have the correct
directory.
In 1.*
you could do could spawn a new module from the sh
module, one which
had customized defaults for the special keyword arguments. This module could
then be accessed just like sh
, and you could even import commands from it.
Unfortunately the magic required to make that work was brittle. Also it was not aligned syntactically with the similar baking concept. We have therefore changed the syntax to align with baking, and also removed the ability to import directly from this new baked execution context.
sh2 = sh(_tty_out=False)
sh2.ls()
Becomes:
sh2 = sh.bake(_tty_out=False)
sh2.ls()
And
sh2 = sh.bake(_tty_out=False)
from sh2 import ls
ls()
Becomes:
sh2 = sh.bake(_tty_out=False)
ls = sh2.ls
ls()
In 2.*
, the return value of an executed sh
command has changed (in most cases) from
a RunningCommand
object to a unicode string. This makes using the output of a command
more natural.
To continue returning a RunningCommand
object, you must use the _return_cmd=True
special keyword argument. You can achieve this on each file with the following code at
the top of files that use sh
:
import sh
sh = sh.bake(_return_cmd=True)
Previously, if the first argument of a sh command was an instance of RunningCommand
,
it was automatically fed into the process's STDIN. This is no longer the case and you
must explicitly use _in=
.
from sh import wc,ls
print(wc(ls("/home/<user>", "-l"), "-l"))
Becomes:
from sh import wc,ls
print(wc("-l", _in=ls("/home/<user>", "-l")))
Or:
from sh import wc,ls
print(wc("-l", _in=ls("/home/<user>", "-l", _return_cmd=True)))
None
In 1.*
, _new_session
defaulted to True
. It now defaults to False
. The reason
for this is that it makes more sense for launched processes to default to being in
the process group of the python script, so that they receive SIGINTs correctly.
To preserve the old behavior:
import sh
sh = sh.bake(_new_session=True)