7

I want to create command line aliases in one of my python scripts. I've tried os.system(), subprocess.call() (with and without shell=True), and subprocess.Popen() but I had no luck with any of these methods. To give you an idea of what I want to do:

On the command line I can create this alias: alias hello="echo 'hello world'"

I want to be able to run a python script that creates this alias for me instead. Any tips?

I'd also be interested in then being able to use this alias within the python script, like using subprocess.call(alias), but that is not as important to me as creating the alias is.

5
  • 2
    Aliases are a feature of shells not of python, or most other programming languages come to that. They can be a support nightmare, in my opinion you should avoid then for anything other than keyboard productivity aids. Use functions instead, again though, those are shell functions not python functions. Commented Jun 15, 2016 at 18:16
  • 1
    You can do that with Python, however the alias will only exist for the lifetime of the system command used to create it (i.e. not very long.) Commented Jun 15, 2016 at 18:18
  • If you are using bash/zsh/.. as your shell you can include something like alias hello="echo 'hello world'" in your ~/.bashrc/ ~/.zshrc or alike. There is probably a similar possibility for the Windows Powershell. Commented Jun 15, 2016 at 18:22
  • Can I add the alias to the ~/.bashrc from within the python script? The idea is to have the python script set up the alias for the user to use in the future. Commented Jun 15, 2016 at 19:24
  • 2
    It is just an ordinary text file, so no problem with editing it as long as you are careful. But the change won't take effect until the user starts a new shell; just returning from the function isn'τ enough Commented Jun 16, 2016 at 1:01

2 Answers 2

5

You can do this, but you have to be careful to get the alias wording correct. I'm assuming you're on a Unix-like system and are using ~/.bashrc, but similar code will be possible with other shells.

import os

alias = 'alias hello="echo hello world"\n'
homefolder = os.path.expanduser('~')
bashrc = os.path.abspath('%s/.bashrc' % homefolder)

with open(bashrc, 'r') as f:
  lines = f.readlines()
  if alias not in lines:
    out = open(bashrc, 'a')
    out.write(alias)
    out.close()

if you then want the alias to be immediately available, you will likely have to source ~/.bashrc afterwards, however. I don't know an easy way to do this from a python script, since it's a bash builtin and you can't modify the existing parent shell from a child script, but it will be available for all subsequent shells you open since they will source the bashrc.


EDIT:

A slightly more elegant solution:

import os
import re

alias = 'alias hello="echo hello world"'
pattern = re.compile(alias)

homefolder = os.path.expanduser('~')
bashrc = os.path.abspath('%s/.bashrc' % homefolder)

def appendToBashrc():
  with open(bashrc, 'r') as f:
    lines = f.readlines()
    for line in lines:
      if pattern.match(line):
        return
    out = open(bashrc, 'a')
    out.write('\n%s' % alias)
    out.close()

if __name__ == "__main__":
  appendToBashrc()
Sign up to request clarification or add additional context in comments.

6 Comments

Might want to be sure you gracefully handle the case where the original file is missing its trailing newline.
Could just prepend what you're adding to the file with a newline. :)
Ah I thought that by writing with open(file, 'a') it appended a newline. I've updated my answer
A conformant UNIX text file should have a trailing newline already, but sometimes (when folks are using sloppy practices and/or nonstandard editors) they don't, and in that case, opening in append mode won't fix that automatically. This looks good as-edited.
This works! (alias works for all shells opened after the change like what you said). Thanks Jonathan!
|
2

Here's a simplified analog of the code from @Jonathan King' answer:

#!/usr/bin/env python3
from pathlib import Path  # $ pip install pathlib2 # for Python 2/3

alias_line = 'alias hello="echo hello world"'
bashrc_path = Path.home() / '.bashrc'
bashrc_text = bashrc_path.read_text()
if alias_line not in bashrc_text:
    bashrc_path.write_text('{bashrc_text}\n{alias_line}\n'.format(**vars()))

Here's os.path version:

#!/usr/bin/env python
import os

alias_line = 'alias hello="echo hello world"'
bashrc_path = os.path.expanduser('~/.bashrc')
with open(bashrc_path, 'r+') as file:
    bashrc_text = file.read()
    if alias_line not in bashrc_text:
        file.write('\n{alias_line}\n'.format(**vars()))

I've tried and it works but you should always create a backup file when changing sensitive files:
$ cp ~/.bashrc .bashrc.hello.backup

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.