Ben Chuanlong Du's Blog

And let it direct your passion with reason.

Python Alternatives to Shell

Python Equivalent of Shell Commands

Shell Command Alternative Python
which git shutil.which("git") shutil
mkdir -p /path/to/file Path("path/to/some/file").mkdir(exist_ok=True) pathlib
os.makedirs("/path/to/file", exist_ok=True) os
!mkdir -p /path/to/file IPython
mkdir -p /path/to/file xonsh
cp file1 file2 shutil.copy2("file1", "file2") shutil
shutil.copyfile("file1", "file2") shutil
!cp file1 file2 IPython
cp file1 file2 xonsh
cp -ir dir1/* dir2 shutil.copytree("dir1", "dir2") shutil
cp -r dir1/* dir2 shutil.copytree("dir1", "dir2", dirs_exist_ok=True) shutil
cp -ir /path/to/dir1/ dir2/ shutil.copytree("/path/to/dir1/", "dir2/dir1") shutil
ln -s file1 file2 Path("file1").symlink_to("file2", target_is_directory=True) pathlib
os.symlink("file1", "file2", target_is_directory=True) os
!ln -s file1 file2 IPython
ln -s file1 file2 xonsh
ln -sT file1 file2 Path("file1").symlink_to("file2", target_is_directory=False) pathlib
os.symlink("file1", "file2", target_is_directory=False) os
!ln -sT file1 file2 IPython
ln -sT file1 file2 xonsh
rm file Path("/path/to/file").unlink() pathlib
os.remove(file) os
!rm file IPython
rm file xonsh
rmdir /path/to/dir Path("/path/to/dir").rmdir() pathlib
rm -rf dir shutil.rmtree(dir) shutil
!rm -rf dir IPython
rm -rf dir xonsh
rm -rf file_or_dir if p.is_file():
        p.unlink()
else:
        shutil.rmtree(p)
pathlib + shutil
!rm -rf file_or_dir IPython
rm -rf file_or_dir xonsh
mv file1 file2 Path("file1").rename("file2") pathlib
Path("file1").replace("file2") pathlib
shutil.move("file1", "file2") shutil
os.rename("file1", "file2") os
!mv file1 file2 IPython
mv file1 file2 xonsh
chmod 600 /path/to/file Path("/path/to/file").chmod(0o600) pathlib

IPython

IPython is the best and simpliest Python approach to replace (all part of) shell so far.

  1. Use the IPython shell or JupyterLab notebook (preferred) instead of Shell for complicated interactive operations.

  2. Be careful about illegal shell commands. For example, ls ) in Bash shell throws the error message bash: syntax error near unexpected token ). If you have a equivalent IPython command, it will throw the same error message. For example, suppose file is path of a file which contains ) then !ls {file} in IPython will throws the same error message as above. However, this is definitely trickier to debug than the original Bash shell command ls ). There are several ways to avoid this. First, you can use Python script (xonsh is a great choice is vanilla Python script is too verbose) instead Shell as underlying commands. Second, you can show the underlying Shell commands for debugging.

  3. You can even run Shell commands on a remote server (via ssh or a remote kernel) in JupyterLab notebook. This provide the advantage of leveraging the JupyterLab notebook UI.

xonsh

xonsh is another great Python approach to replace shell. Unlike IPython, xonsh does not require the prefix ! to run arbitrary shell command. However, there is one flaw of xonsh. You cannot use $() and friends in the middle of an argument, which limits its usability serious for complicated shell commands. Please refer to this issue for more details.

plumbum

Yet another Python approach as a replacement of shell. I personally prefer IPython and xonsh to plumbum.

References

  • IPython Magics

  • https://github.com/ninjaaron/replacing-bash-scripting-with-python

  • https://stackoverflow.com/questions/209470/how-to-implement-common-bash-idioms-in-python

  • https://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python

  • https://docs.python.org/3/library/pathlib.html#module-pathlib

Comments