Please help find mistakes I made while trying to set bash aliases [user mode]

Hello, I tried to set some user-level bash aliases, using .bashrc and storing them separately in .bash_aliases file, but it doesn’t seem to be working. There are no error messages, the shell simply doesn’t recognize the alias commands as valid. I largely looked at this Fedora Magazine article in general to guide me.

Here is how I set up my directory in ~/

.
├── .bash_history
├── .bash_history-08471.tmp
├── .bash_history-19786.tmp
├── .bashrc
├── .bashrc.d
│   └── .bash_aliases

(irrelevant files + folders excluded).

I then found a demo script for .bashrc with some arguments that I thought were useful. I pasted it into my .bashrc and edited the paths to reflect my folder structure:


# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]; then
    PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi

# Adding cargo bin path for rmpc & other compiled pckgs
export PATH="$HOME/.cargo/bin:$PATH"

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=


# -----------------------------------
#  Create a new permanent bash alias

#  User specific aliases and functions

#  @param $1 - name
#  @param $2 - definition
# -----------------------------------
new-alias () { 
  if [ -z "$1" ]; then
    echo "alias name:" && read NAME
  else
    NAME=$1
  fi

  if alias $NAME 2 > /dev/null > /dev/null; then
    echo "alias $NAME existe déjà - continuer [y/n]?" && read YN
    case $YN in
      [Yy]* ) echo "bien compris. poursuivrons";;
      [Nn]* ) return;;
      * ) echo "réponse erronée." && return;;
    esac
  fi

  if [ -z "$2" ]; then
    echo "alias definition:" && read DEFINTION
  else
    DEFINTION="$2"
  fi

  if [ -f ~/.bash_aliases ]; then
    echo "alias $NAME=\"$DEFINTION\"" >> ~/.bash_aliases
  else
    echo "alias $NAME=\"$DEFINTION\"" >> ~/.bashrc
  fi

  alias $NAME="$DEFINTION"

if [ -d ~/.bashrc.d ]; then
    for rc in ~/.bashrc.d/*; do
        if [ -f "$rc" ]; then
            . "$rc"
        fi
    done
fi
}
unset rc

Then I verified that the shell is interactive using these instructions, and non-login using these instructions, and then executed the shell before rebooting.


~$ [ -z "$PS1" ] && echo "This shell is not interactive" || echo "This shell is interactive"
This shell is interactive
~$ echo $0
/usr/bin/bash
~$ source ~/.bashrc

Nothing happened upon multiple reboots (I just didn’t touch this for a while, had other work to do).

Finally, this is everything that I set in ~/.bashrc.d/.bash_aliases :

alias uu1='systemctl --user enable mpd && systemctl --user start mpd'
alias uu2='rmpc'
alias uu3='systemctl --user disable mpd'
alias uu4='pkill rmpc'
alias grep='grep --color=auto'
alias uefi='systemctl reboot --firmware-settings'

Could someone please take a look and let me where the issue lies? Is it in the .bashrc syntax? For example, did I place the closing bracket } in the correct place? (I wasn’t sure). Or something else?

(Please note that the command to set $PATH for cargo (Rust-compiled music app rmpc) was executed properly. I did that one a while ago. So the file overall seems to be ok.)

Thank you!

This Reddit thread (from someone with a similar script) might be useful.

Particularly, the top answer notes that the wildcard in ~/.bashrc.d/* doesn’t match dotfiles by default, so it doesn’t consider your ~/.bashrc.d/.bash_aliases.

4 Likes

Thanks. I was reading from a previous thread here, and it seems that the dotfiles/folders are used for user-only scripts, whereas no dots bashrc.d and associated files in it are system-wide and are in a different directory (/etc/bashrc.d and so on). So that’s what confused me…

I don’t have a non-dot bashrc.d/bash_aliases directory in ~/… I will try to make one and then see if it works.

Ok, by looking over my .bashrc again, I found something that mifght be an error?

In

if [ -f ~/.bash_aliases ]; then
    echo "alias $NAME=\"$DEFINTION\"" >> ~/.bash_aliases
  else
    echo "alias $NAME=\"$DEFINTION\"" >> ~/.bashrc
  fi

should ~/.bash_aliases actually be ~/.bashrc.d/bash_aliases, conforming to my folder structure? Or is the command only using filenames? And would the last if command with ~/.bashrc.d/* just override that anyway?

This is a design choice really. Do you want your .bashrc to source ~/.bash_aliases (which is a common choice)? Or do you want it to source only from files in the directory ~/.bashrc.d/ ?

Also, notice that any (non-dotfile) scripts in ~/.bashrc.d/ currently only get sourced when the function new-alias() is called. Is that what you want, or do you want them to be sourced every time that .bashrc runs?

add a set -evx to the top of your script - it’ll show you each line after expansion has taken place, globbing has been performed and so on.

By running the script and reading the output it produces as it runs, it’ll direct you to where things aren’t operating as you expect (or thought) they would.

1 Like

OK, I think I’m starting to get it. I guess the separate ~/.bashrc.d/ directory only complicates things. So, if I just move the aliases file to source -->> ~/.bash_aliases I think I will be less confused / less lines of script needed in .bashrc

Then I could completely just delete that last snippet:

if [ -d ~/.bashrc.d ]; then
    for rc in ~/.bashrc.d/*; do
        if [ -f "$rc" ]; then
            . "$rc"
        fi

– right?

Also, ideally I would like the scripts to run at boot with .bashrc, as that would just set up the aliases without me doing it manually. Is there a modification to new-alias() function or another function I can use to include the dotfiles? (Noting that I’m going to remove the ~/.bashrc.d/ completely)

thanks!

Thank you. Where do I see the output for this? Is it ~$ journalctl -b? I guess I would run that right after the ~$ source /.bashrc?

Run the script - the output will be sprayed into the terminal as the script runs.

.bashrc won’t run at boot, but it will run each time you start an interactive shell. That’s fine and just what you want here, since the aliases are for your use in your interactive shell.

If you’re removing that directory, then it sounds like you don’t need wildcards, so no need to worry about what the wildcard includes. You can just source that single file ~/.bash_aliases.

You probably want to source it both (a) in the main body of bashrc, outside the function, so it happens when the interactive shell starts, and (b) at the end of the new-alias() function, so that ~/.bash-aliases gets re-sourced including the alias that was just added.

1 Like