Bash Shell Scripting: Input and Output
Standard Outputting echo, printf
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.
- suppress new line
- new line
- carriage return
- horizontal tab
Can we do even better, making sure our code is 100% portable and POSIX standard? Yes, we can with
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!
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.
%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
$ printf "The child is %f years old.\n" 3.5 The child is 3.5 years old.
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.
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.
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
- 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
- Standard Output
- Where the normal output goes.
- Denoted with a
- Standard Error
- Where all error messages are reported
- Attaches second file to bottom of first file.
- Denoted with a
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 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!"
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
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
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.
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:
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
#!/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