[Linux][Shell] Cleaning PATH environment variable.

With using terminal for a long time, PATH variable tends to be longer and longer due to duplicated path.
Here is simple sample script – with Perl – to resolve this.

# remove duplication at give PATH-format-string
unique_path() {
perl -w -e '
    my %path_hash;
    exit unless (defined $ARGV[0]);
    foreach $p (split (/\:/, $ARGV[0])) {
        unless (defined $path_hash{$p}) {
            $path_hash{$p} = 1;
            push @newpath, $p;
        }
    }
    print join ":", @newpath;
' $1
}
...(skip)...
PATH=$(unique_path "$PATH")
...(skip)

Done :-).

Advertisements

[Bash] Miscellaneous informations

— Sub-shell / Current shell —

(*1)
    echo -e "aaa\nbbb\nccc\nddd" > tmp
    value=0;
    while read line; do
        value=$(expr $value + 1)
        echo $value
    done < tmp
    rm -f tmp
    echo "at last: $value"

    result:
    1
    2
    3
    4
    at last: 4

(*2)
    value=0
    echo -e "aaa\nbbb\nccc\nddd" | while read line; do
        value=$(expr $value + 1)
        echo $value
    done
    echo "at last: $value"

    result:
    1
    2
    3
    4
    at last: 0

It is interesting, isn’t it? The main reason is, (*1) is executed in current shell. But (*2) is executed in sub-shell. In more detail, there is only one process(current shell) during run at (*1). But at (*2), there are three processes; current shell, process for ‘echo’ and process for ‘while loop’.

— Shell function —

(*1)
    function func_name() {
        ...
    }

(*2)
    func_name() {
        ...
    }

(*2) is more portable than (*1). Bash supports both (*1) and (*2). But, dash – /bin/sh -> dash in Ubuntu – doesn’t support (*1).

— Syntax —
‘()’ grouping and ‘{}’ grouping is delicately different in it’s syntax.

(echo 1; echo 2; exit 0) # OK
{ echo a; echo b; exit 1 } # syntax error
{ echo a; echo b; exit 1; } # OK

 
— Test —
‘!’ has higher priority than ‘-a’ and ‘-o’.

Assume that there are two files; ‘a’ and ‘b’

[ -r a -a -r b ] : TRUE
[ ( -r a -a -r b ) ] : syntax error
[ ( -r a ) -a ( -r b ) ] : syntax error
[ ! -r a -o -r c ] : FALSE
[ ! -r a -o -r b ] : TRUE

 
— Replacement —
‘~’ isn’t replaced in “”. So,

MYHOME=~ # OK
MYHOME="~" # it doesn't work as expected

 
— Symbolic link —
Assume following file structure.

/data/userA/
/data/userB/
/home/a (a -> /data/userA/)
/home/b (b -> /data/userB/)

Let’s see the following test.

cd /home/
cd a
pwd
    -> '/home/a' is shown.
ls ..
    -> 'userA' and 'userB' are shown. -- (*a)
cd ..
pwd
    -> '/home' is shown -- (*b)
ls
    -> 'a' and 'b' are shown. -- (*c)
cd /home/
cd a
cp a.txt ../
    -> a.txt is created at '/data/' -- (*d)    

As you can see, the way handling symbolic link is different among commands. In above test, ‘cd’ and ‘pwd’ work differently from ‘ls’ and ‘cp’. Some commands – like ‘cd’ and ‘pwd’ – handle directory path of working directory but some – like ‘cp’ and ‘ls’ – doesn’t.
Therefore, try to use ‘absolute path’ to avoid the case like this, if symbolic link is included in the directory path.

[Bash] Shell setup files

From top to bottom

/etc/profile
.bash_profile [ -> .bash_login -> .profile ] : if ‘.bash_profile’ doesn’t exist the ‘.bash_login’…
.bashrc : whenever an interactive shell is started.
.bash_logout : when the login shell is existed.