简体   繁体   中英

bashrc not exporting variable in function when changing directories

I have several projects I work on. Instead of setting aliases for each project's location, I would rather set it when I navigate to that specific directory. Each project is a git repo and I already have a mechanism that appends the current branch name to $PS1 when I navigate to it.

In my .bashrc, I call a function: parse_git_branch to append to command prompt:

case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h:\w\a\]$PS1\$(parse_git_branch) "
    ;;  
*)
;;  
esac

parse_git_branch is defined at the end of my .basrhc:

function parse_git_branch {
    GIT_BRANCH=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/')
    if [[ -n $GIT_BRANCH ]];then
            source $HOME/bin/cur
    fi
    echo $GIT_BRANCH
}

if GIT_BRANCH isn't empty, I source a simple script ~/bin/cur which sets an alias for the pwd:

#!/bin/bash
echo "got here!"
shopt -s expand_aliases
alias current="cd $(pwd)"

When cur is sourced, the alias is not set. The debug message does display correctly however.

I believe this is because shell scripts run "outside" of my current environment. The alias is set when call source cur from the command line.

So, why is the alias not being set when called from "parse_git_branch" inside my .bashrc?

Thanks!

Problem here is usage of $() that runs parse_git_branch in a subshell. As a result, alias current is not found in opened terminal because aliases are not visible by parent processes.

case "$TERM" in
  xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h:\w\a\]$PS1\$(parse_git_branch) "
    source $HOME/bin/cur
    ;;  
*)
;;

should work.

Ok, I figured it out. The issue here isn't why I'm trying to do this. The issue lays in the fact that I'm trying to affect a parent shell environment from a subshell environment spawned from it (The $() command syntax bart spoke of.) So the workaround was to allow communication from both environments. For that, I simply used the filesystem. Here's what I did:

.bashrc didn't have to change much, but it didn't have to source anything either:

parse_git_branch {
  GIT_BRANCH=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/')
  if [[ -n $GIT_BRANCH ]];then
        $HOME/bin/cur -p
  fi
  echo $GIT_BRANCH
}

I modified ~/bin/cur to simply write or read the fs, not attempt to modify any environments:

#!/bin/bash
put() {
  echo $(pwd) > $HOME/.tmpalias
}
get() {
  cat $HOME/.tmpalias
}

case "$1" in
 *p) 
   put
   ;;
 *g) 
   get 
   ;;  
esac

The cur script will either write or read from the file .tmpalias when called (I didn't bother with arguments and files etc since this is only called in two places.

Then I added the following to my .bash_aliases file:

alias current='cd $(cur -g)'

Voila! So I can expand this into an event trapping mechanism that can be invoked for any command I run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM