Bash Tips and Tricks – 2

5 05 2009

After a period of hibernation, I’m meeting you again with some more interesting tips and tricks related to the bash. Hope you’ll find it more interesting than the previous post.

Enabling and disabling an alias

To list the configured aliases you can use the command ‘alias’ you’ll see something like this,

$ alias
alias ls='ls --color=auto'
alias rm='rm -i'

As you can see, rm is aliased as ‘rm -i‘ (to prompt before every removal). So if you try to remove any file using ‘rm‘, its going to prompt you for confirmation.

$ rm file.txt
rm: remove regular empty file `file.txt'? y

Now if you want the use ‘rm‘ command without the alias additions like rm -i, you can do it in two ways:

1 – Un-aliasing a command by simply prefixing the command with a ‘\’

$ \rm file.txt

2 – Using ‘unalias‘ command

$ unalias rm

The above ‘rm‘ one is just an example to illustrate this, you can also do ‘rm -f‘ for the same :-)

Highlight match with color in grep command

Like bash ‘ls‘ command, grep supports color in its output. Which means you can highlight the text that grep matches with color.
This is controlled by ‘–color‘ option with grep command which basically surround the matching string with the marker find in GREP_COLOR environment variable.

$ grep --color=auto <pattern> <file>

You can also change this color by setting the GREP_COLOR environment variable to different combinations from the color code list given below.

For example, to highlight the matched pattern with foreground color black and background color yellow, you can say..

$ export GREP_COLOR='1;30;43'

The set display attributes list:

0 Reset all attributes
1 Bright
2 Dim
4 Underscore
5 Blink
7 Reverse
8 Hidden

Foreground Colours
30 Black
31 Red
32 Green
33 Yellow
34 Blue
35 Magenta
36 Cyan
37 White

Background Colours
40 Black
41 Red
42 Green
43 Yellow
44 Blue
45 Magenta
46 Cyan
47 White

Handling ‘argument list too long’

I have nearly 200,000 files in one of my log directory out of which number of files created in 2007 is 120,000. So whenever I try to do apply some command such as rm, ls or cp etc. on those big set of “*2007*.log” files, I used to get,

$ ls *2007*.log
bash: /bin/ls: Argument list too long

$ mv *2007*.log /backup
bash: /bin/mv: Argument list too long

“Argument list too long” error is occurring due to the limitation of the above commands to handle large number of arguments. But you can get the job done easily using the ‘find‘ command. For example, to copy the files to a separate location, you can say,

$ find .  -name "*2007*.log" -exec cp {} /backup/ \;

Same results can be achieved by the following as well..

find .  -name "k*2007*.log" | while read FILE
    do
    ...
    <some operation on $FILE>
    ...
done

Process substitution

This trick allows you to use a process almost anywhere you can use a file. To illustrate, let’s consider the diff command. Most versions of diff require you to pass exactly two file names as arguments. But what if we want to diff something, like the contents of a directory, that doesn’t necessarily exist in a file? This is where we can use process substitution. For example, to diff the contents of two directories, you could use:

diff <(find dir1) <(find dir2)

The syntax <(command) creates a named pipe, and attaches command’s STDOUT to the pipe. So, anything that reads from the pipe will actually be reading the output of command. To prove this to yourself, try the following:

$ echo <(/bin/true)
/dev/fd/63

$ ls -l <(/bin/true)
lr-x------  1 chamith chamith 64 Jul 13 21:50 /dev/fd/63 -> pipe:[723168]

$ file <(/bin/true)
/dev/fd/63: broken symbolic link to pipe:[728714]

Similarly, you can use the syntax >(command) to have the command read from the pipe. As an example:

tar cvf >(gzip -c > dir.tar.gz) dir

Obviously, there are better ways to accomplish taring and compressing, but the point was to use process substitution.

pushd / popd

Bash will keep a history of the directories you visit, you just have to ask. Bash stores the history in a stack and uses the commands pushd and popd to manage the stack.

pushd foo – move the current directory onto the stack and change to the ,em>foo directory.
popd – pops the top directory off of the stack and moves you into it.

We’re opening files all over the file system, internal code, vendor code, templates, configuration files, logs. Because of this we like the ability to take a detour on the file system and still navigate back to our working directory of the day. I think these commands are so useful that I alias’d them in my .bashrc :

alias cd="pushd"
alias bd="popd"

Now the ‘cd’ command manages the stack for me as well as changing directories. Aliasing popd to bd is an easy to remember and easy to type way to move back up the stack, think “change dir” and “back dir” :)

Hope you’ll find this post useful. Feel free to share your ideas about this post.



Actions

Information

Leave a comment