2

I get Python. I don't get shell script. I could learn shell script, but I would rather not if I can use Python in its place.

A good place for me to start would be the .profile script. Currently, for me it is:

# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# added by Anaconda2 2.4.0 installer
export PATH="/home/alien/anaconda2/bin:$PATH"

# ===== Added manually.

# texlive
export PATH="/home/alien/texlive/2015/bin/x86_64-linux:$PATH"
export INFOPATH="/home/alien/texlive/2015/texmf-dist/doc/info:$INFOPATH"
export MANPATH="/home/alien/texlive/2015/texmf-dist/doc/man:$MANPATH"

# petsc
export PETSC_DIR="/home/alien/petsc"


# PYTHONPATH
export PYTHONPATH="/home/alien/cncell:$PYTHONPATH"
export PYTHONPATH="/home/alien/csound:$PYTHONPATH"

Instead, I'd like to write something like this:

import os
import subprocess

#  if running bash
HOME = os.environ["HOME"]
if os.environ["BASH_VERSION"]: #not sure how to complete this line 
    bashrc_path = os.path.join(HOME, ".bashrc")
    if os.isfile(bashrc_path):
        subprocess.call([bashrc_path])

user_bin_dir = os.path.join(HOME, "bin")
if os.isdir(user_bin_dir):
    os.environ["PATH"] += ":" + user_bin_dir

user_added_vars = [("PATH", "/home/alien/anaconda2/bin"),\
                   ("PATH", "/home/alien/texlive/2015/bin/x86_64-linux"),\
                   ("INFOPATH",  "/home/alien/texlive/2015/texmf-dist/doc/info"),\
                   ("MANPATH", "/home/alien/texlive/2015/texmf-dist/doc/man")]

for var_name, addition in user_added_vars:
    os.environ[var_name] += ":" + addition

This is just more readable/familiar to me.

Is it possible to somehow write Python scripts where bash scripts are expected? I think an answer to an earlier question of mine might be useful, perhaps we just stick #!/usr/bin/env python at the top of the script to designate it as a "Python script"? But then, why isn't there a #!/bin/bash line at the top of the current .profile?

bzm3r
  • 363
  • 1
  • 2
  • 15
  • 3
    Simple answer: no, not in the profile, because the profile is sourced from your shell. Meaning, it's not run in a separate process—the lines of text in your .bash_profile work exactly the way they would if you typed them directly on the command line. (Of course this filename .bash_profile assumes you are using bash as your interactive shell, but in any shell I know about your profile is sourced rather than run as a script.) – Wildcard Dec 10 '15 at 05:21
  • As far as what bash and bash scripts are for conceptually, I can't imagine any clearer explanation than what is found here: http://unix.stackexchange.com/a/169765/135943 Should be the first thing read by any relatively experienced programmer seeking to learn bash. – Wildcard Dec 10 '15 at 05:25
  • @Wildcard: Files such as .profile must be sourced, not run in a subshell, or there'd be no way for them to set shell and environment variables. I can't see how any shell would be able to do that. – Tom Zych Dec 10 '15 at 09:48
  • 1
    @TomZych: Right, that was my point. I didn't state it absolutely only because I know virtually nothing about the more esoteric shells such as fish, tcsh or pyshell. – Wildcard Dec 10 '15 at 15:58

1 Answers1

2

Not really. The .profile and .bashrc (and .bash_logout and .bash_profile) are specific to the shell. That is, the shell programs and only the shell programs read these files. It (the shell) does not execute these as a separate process, but rather source them, in a way similar to how Python does an import, but far less elegantly. If you want something similar, you need to find a python-based shell. An answer to that related question is found here.

The closest you can get is a python script that does its work and then exports its shell-compatible KEY=VALUE pairs, prints them to standard out, and then in the .profile or whatever, you have (for instance):

set -a
eval `python $HOME/.profile.py`
set +a

You must, however, take care of several things. First, all these VALUEs must be appropriately quoted. Usually, you want single-quotes, unless the VALUE contains single-quotes. Second, certain shell variables should not be overwritten (unless you know what you're doing): SECONDS, RANDOM come to mind.

By the way: The set pair turn on and off automatic exporting, so that whatever variables you send from python to the shell, then get exported by the shell to sub-processes. This isn't necessary if your python script precedes each KEY with the term export. (However, strictly speaking, that's incompatible with the original Bourne shell.)

Otheus
  • 6,138
  • I'm not looking for a way to glue together Python and bash, so only the first two sentences of this answer are truly useful to me. The third sentence, referring to another question, is a less detailed version of the question chain I already referred to. Could you update the answer based on this? I have also set up a new, more relevant question here: http://unix.stackexchange.com/questions/248614/how-do-i-replace-my-base-system-shell-with-ipython – bzm3r Dec 10 '15 at 17:51
  • Could you update your question to better suit my answer :P I updated my answer to address the very last question in your original post.

    You seem to have two separate use cases: (1) writing code to do things useful in setting your environment -- which I address above; (2) interactively using a UNIX system, which you seem to ask in your 2nd question. Fact is, the shell is the best way to interact with the system. If you want to avoid fancy scripting, but still need to use the results, the above answer is a fine way to do it.

    – Otheus Dec 17 '15 at 10:57