Some Computer Hints


Bash General

There is an important difference between Bash and POSIX Shell. The commands:

$ grep root /etc/passwd | IFS=: read -r user x1 uid gid x2 home shell
$ echo $uid $home

do not produce the desired output. The read command runs in a subshell and the values it reads are lost when we come to the echo command. Solutions to this problem are as follows:

$ { IFS=: read -r user x1 uid gid x2 home shell ; } <<EOS
$(grep root /etc/passwd)
EOS

or simply

$ IFS=: read -r user x1 uid gid x2 home shell <<<$(grep root /etc/passwd)

or using process substitution (see below)

$ IFS=: read -r user x1 uid gid x2 home shell < <(grep root /etc/passwd)

To process multiple lines you can use this:

$ while IFS=: read -r user x1 uid gid x2 home shell ; do
echo $uid $home
done < /etc/passwd

The command

$ command &>filename

redirects both the stdout and the stderr of command to filename. Use &>> for appending.


Use the -e option with echo to print escaped characters. For example,

$ echo -e "\v\v\v\v"

prints vertical tabs.


The tab character is usually used for command completion in Bash. So, you cannot type in a tab character using the Tab key in command line. Use Ctrl+V and then the Tab key. That will put a literal tab character on the command line, which can be useful if you need to grep a tab in a tab-delimited text file, for example.


The /dev/urandom device-file provides a means of generating much more random pseudorandom numbers than the $RANDOM variable.


To do random I/O in Bash, in other words to write at a specified place in a file, use something like in the following example:

$ echo 1234567890 >File   # Write string to "File"
$ exec 3<> File           # Open "File" and assign fd 3 to it
$ read -n 4 <&3           # Read only 4 characters
$ echo -n . >&3           # Write a decimal point there (on 5th character)
$ exec 3>&-               # Close fd 3
$ cat File                # will return "1234.67890"

You can use process substitution to eliminate the need of saving intermediate command outputs to temporary files. For example, to compare the contents of two directories (to see which filenames are in one, but not the other) execute

$ diff <(ls first_directory) <(ls second_directory)

You can use the special device directory /dev/tcp/ in Bash to do socket I/O. For example, to get current time from a time server (e.g. time.nist.gov) using daytime port (13) run:

$ cat </dev/tcp/time.nist.gov/13

To download an unencrypted URL do this:

$ exec 5<>/dev/tcp/www.example.com/80
$ echo -e "GET http://www.example.com/ HTTP/1.0\n" >&5
$ cat <&5