Standard Outputting echo, printf
The echo
command is an easy way of outputting data to a user.
$ echo 'Hello world!'
Hello world!
$ echo $PS1
\[\033[1;34m\]\W$\[\033[0m\]
This command is extremely useful, but primitive. Can we do better?
We could use echo
with the option -e
to use escape sequences.
- \a
- alert
- \b
- backspace
- \c
- suppress new line
- \n
- new line
- \r
- carriage return
- \t
- horizontal tab
- \\
- backslash
Can we do even better, making sure our code is 100% portable and POSIX standard? Yes, we can with printf
.
Fancy printing with printf
In order to make a more flexible command that complies with POSIX standards, the printf
command was adopted.
Although certainly more flexible, the printf
command forces the user to be more explicit. For example, the newline character is not defaulted like it is in echo
- we must supply it on our own.
$ printf "Hello world!\n"
Hello world!
Format specifiers
Just like printf
is used in C and many other compiled languages, we may supply it a variable proceeding the declaration. For example:
$ printf "Hello my name is %s %s.\n" Tony Dylan
Hello my name is Tony Dylan.
The %s
is a variable that stands in for strings, while the %d
stands in for integers.
$ printf "I am %d years old" 44
I am 44 years old
$ printf "I am %d years old" 0x2c
I am 44 years old
To print floating point values, use the %f
specifier.
$ printf "The child is %f years old.\n" 3.5
The child is 3.5 years old.
Formatting
To limit decimal places, we can place a decimal point and the precision within the floating specifier.
$ printf "%.2f\n" 3
3.00
To place spaces before a numerical value, we can do so with just an integer value.
$ printf "I am %4d years old.\n" 13
I am 13 years old.
To pad a number with zeros, precede with a zero.
$ printf "I am %04d years old.\n" 13
I am 0013 years old.
Treating "anomalies"
If there are fewer stand-ins than variables supplied, then the shell repeats the line until done.
$ printf "I ate some %s.\n" eggs chicken bacon
I ate some eggs.
I ate some chicken.
I ate some bacon.
On the other hand, if there are more stand-ins than variables, then the shell simply omits them.
$ printf "I ate some %s, %s and %s.\n" eggs chicken
I ate some eggs, chicken and .
Quotes review "", '', ``
Let's do a quick review on the two types of quotation marks and back tick before we move on.
Quotation marks
Here's a quick recap of the differences between the two quotation marks. Head over to our Command Line series lesson for a more in-detailed look.
- Single quotes ''
- Literal values.
- Guarantee shell won't try substitutions.
- Double quotes ""
- Before running the command, shell looks for variables, globs and other substitutions to perform.
- More flexibility with the shell.
- Executes everything literally except for
$
,\
,!
or`
. - Back quotes ``
- Key found on top of left tab key.
- Used to execute commands.
$ echo $123
# Evaluates $1 as positional parameter
23
$ echo "$123"
# Same as above
23
$ echo '$123'
# Literal output
$123
$ printf "Today's calendar: \n`cal`"
Today's calendar:
July 2015
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31:
Standard I/O redirection
Standard in, out and error
The idea behind a standard input and output is that there is a data source, a sink and a place to report all errors.
To summarize standard IO:
- Standard Input
- Used to input data.
- Denoted with a
<
symbol. - Standard Output
- Where the normal output goes.
- Denoted with a
>
symbol. - Standard Error
- Where all error messages are reported
- Use
2>
. - Appending
- Attaches second file to bottom of first file.
- Denoted with a
<<
symbol.
As an example, take this RepeatInput program which reads in an input, then spits it back out.
$ java RepeatInput < "hello world!" > hello_world.txt
# "hello world!" now stored in hello_world.txt
/dev/null
/dev/null is a special place on our UNIX machine that acts as a trash bin. Anything sent to /dev/null is discarded.
If you want to omit all errors when running a program (which you should have a very good reason to do) then you can simply direct error messages to /dev/null.
#!/bin/bash
# Program runs silently by throwing away error messages
java ProgramWithErrors 2> /dev/null
You can also run a script that clears files by overwriting its content with /dev/null
#!/bin/bash
cd /var/log
cat /dev/null > logMessages
echo "Log files all cleaned up!"
Pipelines
There are also pipelines, which are used to take the standard output of one command to be used as the standard input of another command. These commands are joined together by a |
.
Pipelines should be ordered so that you reduce the most amount of data on each step.
$ ls | grep .txt | wc -w
# How many files with .txt extension are in current folder
22
Reading user input read
To read user input into your shell program using standard in, simply use the read
command.
printf 'How are you doing today? '
read user_input
The following will output the question "How are you doing today?" and allow the user to input some string.
Multiple values at once
You may use the read
command to read in multiple values at once, separated by a space.
printf 'Enter your last name, first name, and position: '
read last_name first_name position
printf 'Your last name entered is %s. \n' $last_name
printf 'Your first name entered is %s. \n' $first_name
printf 'Your position is %s. \n' $position
Hinting what the user has to input
We may hint at what info the user has to give by using the -p
option.
printf 'What are your first and last names? '
read -p "First name: " first_name
read -p "Last name: " last_name
This will output "First name: " on the command prompt, notifying the user that he or she needs to type out his first name.
Sample script
Let's try a sample script named name that reads in a user's first name and last name, then outputs it back.
#!/bin/sh
printf "Hello, welcome!\n"
printf "What is your name? \n"
read -p "First Name: " first_name
read -p "Last Name: " last_name
printf "Oh, okay %s %s. \nWelcome to the command line!" $first_name $last_name
Here's what it looks like in action:
$ ./name
Hello, welcome! What is your name? First Name: Ted Last Name: Bundy Oh, okay Ted Bundy. Welcome to the command line!
Reading in passwords
When a user inputs a password, we want to avoid having those characters echoed out. We can do this by turning off echo
with stty
.
#!/bin/bash
printf "Enter a new password: "
stty -echo # Turns off echoing characters
read pass1
printf "\nPlease enter again: "
read pass2
stty echo # Turn echoing feature back on
printf "\nYou entered two passwords: %s and %s.\n" pass1 pass2