LinuxBasics.org

The community that helps people to run Linux

rss
Table of Contents

Puzzling commandlines

In bash, the most common command-line-interpreter in Linux, you can execute more than one command in sequence or concurrently. One command can built upon the results of the others. This is a result of the UNIX-philosophy: “Many small programs that each do one task well.”

stdin, stdout and stderr - redirection - '<', '>', and '>>'

While most shell-commands can take filenames for input and output, a common concept is that of standard-input (stdin, usually the keyboard) and standard-output (stdout, usually the screen) for regular input and output. The standard-error (stderr, usually also the screen) is for error-messages and warnings that refer to the execution of the program, not to the result.

Let’s take the calculator ‘bc’ as an example:

stw@sixty-four:~> bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
17+4
21
6*7
42
2000+1
2001
stw@sixty-four:~>  

All I entered (with my keyboard = stdin) was ‘bc’, ‘17+4’, ‘6*7’, and ‘2000+1’, each with the enter-key terminating the line. <ctrl-D> terminated the input.

I now prepare a file with these calculations in it: I do a ‘cat’, without an input-filename (thus it will read from stdin, which is the keyboard). ‘cat’ prints whatever I type to stdout (which is redirected to the file ‘calculations’). The second cat is simply to check the file that just has been written. ‘bc’ is then invoked with stdin redirected to read from the file ‘calculations’.

stw@sixty-four:~> cat  >calculations
17+4
6*7
2000+1
stw@sixty-four:~> cat calculations
17+4
6*7
2000+1
stw@sixty-four:~> bc <calculations
21
42
2001

Now I want to add some more lines to ‘calculations’. Instead of retyping the old ones again, I append to the file using the ‘»’ redirection. The results of ‘bc’ are redirected to the file ‘calculation-results’. Only the error message will be printed on the screen (since stderr is not redirected):

stw@sixty-four:~> cat  >>calculations
42/(9+3-12)
stw@sixty-four:~> bc <calculations >calculation-results
Runtime error (func=(main), adr=17): Divide by zero
stw@sixty-four:~> cat calculation-results
21
42
2001

We can also redirec stderr. First we redirect it to a seperate file, then to /dev/null (thus into the void), and last to stdout (which then can be parsed by other commands through a pipe).

stw@sixty-four:~> bc <calculations >calculation-results 2>calculation-errors
stw@sixty-four:~> cat calculation-errors
Runtime error (func=(main), adr=17): Divide by zero
stw@sixty-four:~> bc <calculations >calculation-results 2>/dev/null
stw@sixty-four:~> bc <calculations >calculation-results 2>&1
stw@sixty-four:~> cat calculation-results
21
42
2001
Runtime error (func=(main), adr=17): Divide by zero

Pipes - '|'

Pipes connect stdout of one program to stdin of the next. Thus the second command can operate upon the output of the first.

Let’s count the users of a system. They are all listed in ‘/etc/passwd’. So we count the lines in that file. The second line has also a ‘grep’ in the pipe which will only let those accounts with a 4-digit uid go through, which are in my case those for regular users.

stw@sixty-four:~> cat /etc/passwd | wc -l
32
stw@sixty-four:~> cat /etc/passwd | grep :x:[1-90][1-90][1-90][1-90]: | wc -l
12

Thus I have 32 accounts, 12 of which belong to ‘real, life beings’.

Backticks - '$(...)'

Backticks ‘`’ (accent-grave in french - comme sur le e dans ‘bière’) are used to use the output of a command on the commandline. Since they are easily mistaken for regular quotes, their use is deprecated. $(…) accompishes the same thing:

export FN=`date +%Y-%m`
export FN=$(date +%Y-%m)

will take the output of the date-command and assign it to the shell-variable $FN. This is usefull for scripts that need the current date. See the daily-backup script in Backup your data

ls -l $(which mozilla)

will take the output of the which-command and use it as argument for ls. This is usefull to check the permissions on executables.

The full examples:

stw@sixty-four:~> date +%Y-%m
2005-09
stw@sixty-four:~> export FN=$(date +%Y-%m)
stw@sixty-four:~> echo $FN
2005-09
stw@sixty-four:~> which mozilla
/usr/bin/mozilla
stw@sixty-four:~> ls -l /usr/bin/mozilla
lrwxrwxrwx  1 root root 27 2005-09-30 12:47 /usr/bin/mozilla -> /opt/mozilla/bin/mozilla.sh
stw@sixty-four:~> ls -l $(which mozilla)
lrwxrwxrwx  1 root root 27 2005-09-30 12:47 /usr/bin/mozilla -> /opt/mozilla/bin/mozilla.sh

Sequencial execution - ';'

The semicolon ‘;’ seperates two commands as if they were typed on two seperate lines:

stw@sixty-four:~> cat /etc/HOSTNAME
sixty-four.krone.local
stw@sixty-four:~> cat /etc/SuSE-release
SuSE Linux 9.3 (x86-64)
VERSION = 9.3
stw@sixty-four:~> cat /etc/HOSTNAME ; cat /etc/SuSE-release
sixty-four.krone.local
SuSE Linux 9.3 (x86-64)
VERSION = 9.3

Conditional execution - '&&' and '||'

Two ampersands ‘&&’ will execute the second command only if the first one was successfull:

stw@sixty-four:~> cat /etc/HOSTNAME && cat /etc/SuSE-release && echo Both cats meeowed!
sixty-four.krone.local
SuSE Linux 9.3 (x86-64)
VERSION = 9.3
Both cats meeowed!
stw@sixty-four:~> cat /etc/HOSTNAME && cat /etc/NO-SUCH-FILE && echo Both cats meeowed!
sixty-four.krone.local
cat: /etc/NO-SUCH-FILE: File or directory not found.

Two pipes ‘||’ will execute the second command only if the first one failed:

stw@sixty-four:~> cd some-directory || mkdir some-directory
bash: cd: some-directory: File or directory not found
stw@sixty-four:~> cd some-directory || mkdir some-directory

On the fist invocation of the line, ‘some-directory’ did not exist yet. The ‘cd’ failed and thus the directory was created. The second time, the ‘cd’ was successfull, thus the ‘mkdir’ was ignored.

Concurrent execution - '&'

The single ampersand ‘&’ seperates two commands that will run at the same time.

The following line will start openoffice, firefox, and emacs. Bash will wait for emacs to terminate before it displays the prompt again. It will neither wait for openoffice nor firefox.

stw@sixty-four:~> soffice & firefox & emacs
[1] 30529
[2] 30530

openoffice and firefox run in the background while emacs runs in the foreground. Press <ctrl-z> to put emacs to sleep. Bash will return, but emacs will not respond to your input. Use ‘bg’ to let emacs run in the background. It will respond again. ‘fg’ will put it into the foreground again. <ctrl-c> kills the foreground process (here emacs).
Specifying the process number which bash gave you for ‘soffice’ and ‘firefox’ lets you put those into foreground and background as you like. Confusing? Yes :)

Real life examples:


Copyright (c) by the authors.
Prior to editing, authors agreed to license their contributions by the terms of the GPL.
See our licensing page for details.


Linux® is a registered trademark of Linus Torvalds.


 
  tutorials/advanced/realworld/puzzling_commandlines.txt · Last modified: 2008/07/20 19:08

LinuxBasics.org

Start Linux-Course Tutorials Linux Links Security Blog Forum E-mail List Search Online Chat

Site-Info

Help Get in Touch Making of LBo

Wiki-Control

Powered by

Linux Apache DokuWiki Mailman RUTE ht://Dig