In Core Java Career Essentials book, I had covered some of the core UNIX commands that are useful to Java developers with practical and real life examples. This blog expands on it with some handy UNIX features to complement the book.

Q. Where would you use the control operators like ";", "&&", and "||" in UNIX?A. These control operators are used to combine different commands in a single line. There is a difference between the characters in a sense how the subsequent commands are executed. For example,

The following commands use a ";" to separate commands. This means both the commands will be executed regardless of the first command is successful (i.e. exit code of 0) or not (i.e. exit code other than 0);

$ cd Temp; echo $(pwd)

You could get an output shown below if there is folder named Temp.

/c/Temp

If the folder named Temp is not present, you will get an error and the current directory printed.

sh: cd: Temp: No such file or directory
/c

So, what if you want to only print the current directory if the first change directory command is successful? This is where the "&&" operator comes in handy.

$ cd Temp && echo $(pwd)

In the above example, the echo command will only be excuted if the change directory command is successful. If not successful, only an error will be thrown, and the current directory will not be printed. There are situations where
you might want to do the reverse. That is, execute the second command only if the first command fails. For example, make a "Temp" directory only if the change directory fails. This where the "||" operator comes in handy.

$ cd temp || mkdir temp && cd temp && echo $(pwd)

If, temp directory is not found, make a new directory named temp, and if make direcory is successful, change to that directory and echo the current directory.

Q. What do you uderstand by 2>&1 in UNIX?A. In UNIX you have STDIN, which is denoted by number 0, STDOUT, which is denoted by 1, and STDERR, which is denoted by 2. So, the above line means, the error messages go to STDERR, which is redirected to STDOUT. So, the error messages go to where ever the STDOUT goes to. For example, The following command creates a multiple directories for a maven based Java project. if the the directory creation is successful, change directory to "project" and print the directory tree structure. The STDOUT and STDERR are directed to the file named maven-project.log under the project folder.

Q. What is /dev/null?A. It is a blackhole. For example, in the earlier example, if you want to ignore error like "sh: cd: Temp: No such file or directory" being printed, you can redirect your output to /dev/null. For example

$ cd temp > /dev/null 2>&1 && echo $(pwd)

will fail silently and nothing will be printed if there is no "temp" folder. The message has gone into the blackhole. If there is a "temp" folder, the present working directory (i.e. pwd) will be printed out.

Q. How would you go about the following scenario -- You had to move to another directory temporarily to look at a file, and then move back to the directory where you were?A. One way is to start with "/c/Temp" folder

$ cd ../projects/JMeter
$ cd ../../Temp

The better way is to use the pushd and popd commands. These commands make use of a "stack" data structure using the "Last In First Out" approach.

changes to the /c/Projects/JMeter folder and prints the stack

$ pushd ../projects/JMeter

The stack is printed as shown below.

/c/projects/JMeter /c/Temp

The /c/projects/JMeter will be popped out of the stack and the directory will change back to /c/Temp

$ popd

If you want pushd to not print the stack, you could direct the output to the black hole /dev/null as shown below.

$ pushd ../projects/JMeter > /dev/null

The above is a trivial example, but in real life, you may want to navigate between more number of directories and this stack based approach will come in very handy without having to use the "cd" command. Also, very useful in UNIX scripts. Use it astutely without having to build up a gigantic directory stack full of useless directories.

Q. In UNIX, only nine command line arguments can be accessed using positional parameters. How would you go about having access to more than 9 argumnets?A. Using the shift command. For example, in unix, when you run a command like

The ${0} is test-bash.sh, and ${1} is file1, ${2} file2 and so on till ${9}, which is file9. In the program, if you want to access file10 after processing file1 to file9, you need to use the "shift" command.

$ shift

All it does is move all the command line arguments to the left by 1 position. Which means the file1 will be moved out, and file2 becomes ${1} and file10 becomes ${2}. If you shift it agian, the file3 becomes ${1} and file11 becomes ${9}. In a nutshell

${#} - Total number of arguments
${0} - Command or the script name
${1},${2}, ${3} - First, second and third args respectively.
${*} - All the command line arguments starting from $1.
${@} - Same as ${*} except when it is quoted "${@}" will pass the positional parameters unevaluated. For example, echo "${@}" will print

echo "$1" "$2" ...

Q. How will you go about writing a UNIX shell script, that reads one or more data files like the one shown below and perform a particular task like logging the information in the file or making database calls to patch some data?

A. The sample script below will be predominantly making use of the commands discussed above. If not clear, try to read and understand the above Q&As. The best way to learn is to try it out yourself. The lines starting with "#" are comments. If you do not have a UNIX environment, download a windows UNIX emularor like MSYS or CYGWIN to run it on your WINTEL platform.