Bash – How to make a multiline alias in Bash

aliasbashfunction

I want to make an alias for a multiline ​command to call it faster then copying-pasting-executing it from a text file each time.

An example for such command is this execute-a-remote-updater command:

(
cd "${program_to_update_dir}"
wget https://raw.githubusercontent.com/USER/PROJECT/BRANCH/update.sh
source update.sh
rm update.sh
)

A couple of years ago I have learned that multiline commands' aliases are impossible due to Bash design limitations but perhaps since then the program has been changed and now it is possible.


I think that if it is still impossible, perhaps I could make a function with that code, export it to all shell sessions (although I rarely work with any subsessions and I don't even recall when I last did that), and then call it somehow.

Should it be enough and secure to just wrap it in an exported and named function in say .bashrc or .bash_profile and then call it whenever I need to?

Best Answer

  • It's not impossible at all.

    alias thing='(
    cd "${program_to_update_dir}"
    wget https://raw.githubusercontent.com/USER/PROJECT/BRANCH/update.sh
    source update.sh
    rm update.sh
    )'
    

    or,

    alias thing='( cd "${program_to_update_dir}"; wget https://raw.githubusercontent.com/USER/PROJECT/BRANCH/update.sh; source update.sh; rm update.sh )'
    

    The thing with aliases is that quoting may be tricky to get right as they are text strings, and that they are better suited for really short things, like

    alias ls='ls -F'
    

    In almost every other instance, you want a shell function instead:

    thing () (
        cd "${program_to_update_dir}"
        wget https://raw.githubusercontent.com/USER/PROJECT/BRANCH/update.sh
        source update.sh
        rm update.sh
    )
    

    Or, corrected to not use the update.sh name in the current directory (it may be taken by an unrelated file) and to only run wget if the cd succeeded, and slightly streamlined for the bash shell,

    thing () (
        cd "$program_to_update_dir" &&
        source <( wget --quiet -O - 'https://raw.githubusercontent.com/USER/PROJECT/BRANCH/update.sh' )
    )
    

    (Note that you may want to run the update.sh script using bash instead of sourcing it, or pipe it to bash -s, or use whatever interpreter its #!-line uses. The fact that you're using source on it is confusing as you're also running it in a subshell. The effect on the environment of running the script with source, which is usually why one wants to source a script, is lost when the subshell terminates.)

    Shell functions may be define in the same initialization file that you define aliases in, and they are used in the same way as aliases, but are more versatile (can take arguments etc.)

    The bash manual contains the statement

    For almost every purpose, aliases are superseded by shell functions.

  • Related Question