5

This question already has an answer here:

I search everywhere and almost everyone was suggesting to open the ~/.bashrc or ~/.bash_aliases, then put the alias command there, I created a function name palias as permanent alias function and put it in ~/.bashrc:

function palias(){ echo "alias $1='$2'" >> /home/User/.bashrc;}

So now if I want to permanently alias some command I just :

palias update "sudo apt-get update"

I wonder if there is a built in command like this function, or anything like this to install from repositories?

marked as duplicate by αғsнιη, Sylvain Pineau, Volker Siegel, Eric Carvalho, Kaz Wolfe Oct 8 '14 at 7:58

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    1) You can find a complete list with all builtin commands only by typing helpin your terminal; you will not find nothing appropriate to your function. 2) Do you really need a special package to install it for such a small function? It is probably more quickly to write it than to install it... – Radu Rădeanu Aug 5 '14 at 7:36
  • 3
    as a side note, you should add grep $1 /home/User/.bashrc right before you modify your .bashrc, to at least notify the user that there is already an existing alias with this name – Aserre Aug 5 '14 at 9:27
  • 1
    @Pandya I believe OP used this line as an example. With his function he can add any other command as an alias without editing bashrc – Aserre Aug 5 '14 at 14:08
  • 1
    @EliahKagan OP already knows how to create an alias (witness the function OP has shown us). The question is: is there an app/builtin which does what the function does? – muru Oct 6 '14 at 15:51
  • 1
    @muru You're right--while I think How do I create a permanent Bash alias? does offer insight into this problem beyond what the OP has demonstrated in the question, I was quite wrong to think of this as the same question, or of the answers there as answering this. – Eliah Kagan Oct 6 '14 at 17:56
2

There is no bash builtin to add permanent aliases. Such aliases are created by adding them to a configuration file that is sourced by interactive shells, as you've done with .bashrc.

But you might consider modifying your palias() implementation by making it put the aliases in a separate file. I think this may be considered an improvement, for five reasons:

  1. The file that is mostly edited automatically can be separate from the file that is mostly edited manually. If you need to see what has happened--out of curiosity, or to investigate a problem--this separation may be helpful. (Or if the function is accidentally called many times, creating a large number of unnecessary lines, the damage will be somewhat more contained.)

  2. By putting the individual, automatically generated alias definitions elsewhere than .bashrc, you create a system that "works behind the scenes," which is often what people want when they look for a dedicated builtin to perform a task.

  3. .bashrc is already usually quite complicated. It will be easier to read and modify for unrelated purposes if it's not filled with many user-defined automatically appended aliases.

  4. Simple implementations of palias() -- including what you've written and what I'm about to recommend -- will create bad lines if the file they're appending to is not already newline-terminated (or blank). Normally text editors do this for you but it's possible to accidentally end a text file without a newline, in which case palias() will create a munged-together line that may or may not be correct, and which either way would be very difficult to read. By putting aliases in a separate file that you rarely, or at least less frequently, edit manually, you decrease the risk of this.

  5. If you ever expand your palias() implementation to read the existing contents of its target file, for example, to give useful warnings, it may be much easier to do so if can be assumed to consist entirely of alias definitions. (Or, for more sophisticated parsing: entirely of alias definitions and lines assumed to be wrong.)

  6. It is already widely suggested (though admittedly not as any sort of strong admonition) to put new aliases in a separate file: .bash_aliases

    See How do I create a permanent Bash alias? for more information about places to put aliases.

Default .bashrc files in Ubuntu contain the code:

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

Thus if you create .bash_aliases, it will be used. The command to define the palias() function can then be:

palias() { echo "alias $1='$2'" >> ~/.bash_aliases; }

That command should still go in .bashrc, but the aliases it creates will be placed in .bash_aliases.

More sophisticated implementations are possible. You could:

  1. Run the definition as well as adding it, so it's immediately usable. This is suggested in osirisgothra's answer. I'd use:

    palias() { echo "alias $1='$2'" >> ~/.bash_aliases; alias "$1=$2"; }
    
  2. Check to ensure .bash_aliases is nonexistent, empty, or newline-terminated, and if it is nonempty but not newline-terminated, append a newline prior to the alias definition.

    palias() {
        local target=~/.bash_aliases
        [[ -f "$target" && -n $(tail -c1 "$target") ]] && echo >> "$target"
        echo "alias $1='$2'" >> "$target"
    }
    

    See Gilles's answer to Add missing newlines in multiple files for details on detecting missing newlines with tail.

  3. Check and warn about defining an alias that has already been defined in .bash_aliases.

    Ploutox suggested that idea. But I do not recommend using grep $1 ~/.bash_aliases or similar, because it will produce frequent false positives, anytime $1 matches any part of another alias's definition, and occasional false negatives. The matter is further complicated by how some valid bash aliases, taken as regular expressions, match more than themselves--+ and . actually get used in command and alias names--and a few don't match even themselves.
    grep "alias $1=" is better but mitigates the problem only partially. A leading ^ in the pattern would pretty well match only the leading alias name of a definition, but not address the problem of regexp metacharacters in $1, while using grep -F would strip all metacharacters of their special meaning but in doing so prevent ^ from being used.

    greping .bashrc in this way is even worse than .bash_aliases, as there's an essentially unlimited variety of text that may be part of that file, mostly outside any alias definitions.

    If you want to check for aliases that are defined in the current shell, whether or not they're written in .bash_aliases (or anywhere), you can use alias "$1" (or run alias with no arguments and match, carefully, against its output). Credit goes to muru for this idea. It does have the disadvantage that if you define an alias with alias to test it out and then make it permanent with palias, you'll get a warning even though it was not yet permanent and everything is fine.

    To check new permanent aliases against the contents of .bash_aliases, you could do something like this:

    palias() {
        local target=~/.bash_aliases
    
        if grep -Pqs '^[ \t]*alias[ \t]+\Q'"$1"'\E\=' "$target"; then
            printf "%s: %s: warning: defining \`%s' again in %s\n" \
                        "$0" "$FUNCNAME" "$1" "$target" >&2
        fi
    
        echo "alias $1='$2'" >> "$target"
    }
    

    That seems to work well, though I suspect there are more elegant ways. (Arguably [ \t]* should be removed, if you take leading whitespace before alias as a suggestion that it is part of a multiline alias definition.) It will malfunction if \E appears in $1, but shell metacharacters and quoting characters like \ aren't valid in alias names, so you won't need to give that as input.
    Ideally, on any wrong input, any user-facing function you call would perform no operation except printing a useful error message. But by the nature of palias(), at least unless you're prepared to make its definition far more sophisticated (see below), the burden of reasonable input already falls mostly on the user. You can write non-aliases and alias definition syntax errors to .bash_aliases with this function, and while that's probably acceptable given the way you'll be using palias(), choking on \E is minor in comparison.

    More seriously, alias name1='def1' name2='def2' ... is perfectly good syntax for the alias command, but I haven't tried to parse out alias definitions given as subsequent arguments to alias in .bash_aliases, as I believe correctly determining where the first non-quoted blank occurs would be non-trivial.

    Therefore, if you use the above palias() implementation and also sometimes manually define aliases in .bash_aliases (or whatever file you use as $target), you should define just one alias per alias ... line if you want to have reliable warning behavior.
    It will also fail to recognize alias definitions to the right of a ; or other connectives, for example to chain separate alias commands on the same line, but it seems unlikely you'd want to do that in .bash_aliases.

  4. Parse $1 to ensure it is a valid name for an alias.

  5. Parse $2 to attempt to figure out if it is a plausible body for an alias, and if it is not, then warn, fail, or (where applicable) quote it properly. For example, what happens if a ' character appears in $2?

  6. Do a simpler version of that instead, just checking for and addressing ' in $2.

But you likely don't want to bother with any of that. You know how your function works, its limitations, and how to use it properly. I see four options for you that are at the same time reasonably good and pretty simple:

  1. Just keep using what you have now.
  2. Use an implementation as above, putting the aliases in .bash_aliases instead of .bashrc.
  3. Make a third file for automatically added aliases, and source that file separately (either in .bashrc or .bash_alises.
  4. Don't use a palias() function at all, and just manually add aliases by editing .bash_aliases or .bashrc.
  • I'm not sure if there's a pitfall involved, but wouldn't the simplest way to check for an alias be alias itself (assuming the function runs the definition immediately)? – muru Oct 6 '14 at 18:01
  • 1
    @muru As you say, if palias() is also being modified to run the alias definition, I think that's a reasonable way to do it. Parsing .bash_aliases (or whatever file) has the limitation that the alias might be defined elsewhere. However, checking with alias has its own drawback: a user may manually define an alias (not using palias), see if they like it, and then write it to .bash_aliases with palias. This would produce a warning, when probably no warning is appropriate. – Eliah Kagan Oct 6 '14 at 18:21
1

I suggest (of course you don't have to) putting an eval "$_" after the echo command, so the alias is added right away, and a grep -Pq "alias $1" && return at the start, to make sure that (1) you don't have duplicate alias names, (2) aliases get defined right away instead of waiting for them to be re-sourced.

If you want to get even more creative (this is how I do it), also allow it to take a number from your history, and define it as an alias, or a group of numbers assigned in sequence to one alias, or more, etc.

I've put quite a lot of work into my own .bashrc over the years -- I do share it under a project called gxbase, but since it is "my preferences" it most likely is not what "other people" want. Configuration settings are a very personal thing. Most people expect things to look like /etc/skel/.bashrc, and stuff like bash completion stops working if you set too many custom options :) Just for fun though, my link is http://gitorious.org/gxbase. The file is in extras/my.bashrc/* (see PS at bottom if interested).

As for your question, there are many people out there who post their so-called 'ultimate .bashrc settings' but alas they are only ultimate for them, my answer is: you will be happiest if you create this file yourself, and believe me, for the love of all that's holy; make [offline] backups!!! :) A 'hard (printed) copy' is a good way to plan it further if you want to get even more creative!


PS: The contents of .bashrc-git are a fork from the gitsh project, so most of the credit for that one goes to that guy, and the perlconsole & aptsh integration also are not mine (entirely). You'll have to install the modded perlconsole & aptsh files to get that fully integrated into virtual directories.

  • It is about a year for me too, that I am creating my own custom bashrc. and I am using Aptik for backup in hard drive. also I created a cronjob so it backup automatically. – Arsinux Oct 6 '14 at 20:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.