Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to create local aliases while I work in certain directories. For example, I would like to have the following in a file named local_alias

alias foo='bar'

I wanted to write a cleanup script to remove these aliases after I finish working. Something like:

egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
  un$i
done

If I change the middle line to echo un$i, the output is what looks like a properly formatted unalias command: unalias foo. But as written, I get unalias: foo: not found.

If I try quoting the middle line: "un$i", I instead get unalias foo: command not found.

What am I doing wrong?

share|improve this question

2 Answers 2

up vote 3 down vote accepted

The aliases are specific to the shell, so when you run your script like this:

#!/bin/bash

...
unalias ....
...

It's running as a child shell, which will typically not have the same aliases. Compounding the problem you're also dealing with another issue. As soon as the script terminates the child shell whose aliases have been removed goes away, returning you to the parent shell which still has its aliases intact.

There is no way that I'm aware of to have your current shell's aliases modified in this manner.

So then how to do this?

You can construct an alias or a function within the scope of the current shell itself to perform this action.

Example

alias solution

$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'

function solution

$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
    while read i; do un$i; done; }

Issues with the above

The OP provided these solutions to this answer which he stated will work in his scenario. But in general you cannot change the aliases in a chain of piped commands like this because each pipe invokes a subshell, which will not be able to touch the parent's shell. So we're back to the same problem as previously with the script.

To get around this you could supply the list of aliases as arguments to a command instead.

Example

$ alias ali1="cmd1"
$ alias ali2="cmd2"

Confirm the aliases in our shell:

$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'

Contents of local_alias:

$ cat local_alias 
alias ali1="cmd1"
alias ali2="cmd2"

This command will parse our the names of the aliases from the file local_alias:

$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2

We can use it to unalias these aliases like so:

$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$

Now when we confirm that they're gone:

$ alias | grep -E "ali[12]"
$
share|improve this answer
    
This led me to a solution: just define the loop as an alias: alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'. But, I don't have enough reputation to answer my own question... –  jake May 9 at 1:46
    
@jake - I UV'd your Q, can you now? Your solution is the only way you can do this, you either have to define an alias or a function within the scope of the current shell to effect this type of environment change. –  slm May 9 at 1:48
    
No, need 10 - if you edit your answer I will just accept that. –  jake May 9 at 1:48
1  
@Ramesh - ha, you read my bio thanks =). –  slm May 9 at 2:02
1  
@jake, no issues :) I would like to welcome you to U & L SE :) Glad that your problem got resolved :) Please feel free to ask any question no matter how trivial it is. This is by far the best stack exchange site :) –  Ramesh May 9 at 2:05

It seems that you're running this code in a separate script. This won't do: you need to change the configuration of your running shell, and you can't do that from another process. This cleanup code should be in a function defined in your .bashrc.

A second issue is that the pipe also creates a subprocess (a subshell). So if you run this code inside your interactive shell, the unalias command will remove the alias — but only in the subshell. You need a different approach that doesn't run the unalias command in a subshell.

There are several solutions, but the simplest one would be to build the list of aliases, and then run the unalias command once. Alias names can't contain special characters, so word splitting on the list of aliases will do fine to generate the arguments to unalias.

unalias $(egrep -o "alias [[:alnum:]]+" local_alias)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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