Shell & Friends
Class: CSCE-313
Notes:
I/O redirection in shell
When a program is executed in Linux, it usually has access to three special files: stdin (fd 0), stdout (fd 1), and stderr (fd 2). They correspond to objects cin, cout, and cerr that you're familiar with from C++ programming. The first is connected to the keyboard, while the second and third are attached to the screen or terminal. See Chapter 6, The Linux Command LineLinks to an external site. on IO Redirection. Answer the following questions.
Question 1
To redirect the contents of a file into a command such as md5sum, we can do? In other words you want md5sum to read from file when it's reading from its stdin.
$ md5sum ____ file
Options:
- |
- <
- <<
Overall explanation:
<file redirects the contents of file into stdin of md5sum, so md5sum reads from standard input.<<is a here-document operator, used to provide multiline input written directly in the script, not to read from an existing file.
Question 2
To redirect the output of a command such as date into a file, we can do?
$ date ____ file
Options:
- 2>&1
- |
- <
Overall explanation:
>redirects stdout of date into file, overwriting the file (or creating it if it doesn’t exist).
Question 3
To append the output of a command such as uname to a file, we can do?
$ uname -a ____ file
Options:
- <<
- <
- >>
Overall explanation:
>>appends the command’s stdout to the end of file instead of overwriting it.
Question 4
To redirect only the error messages of a command such as find to a file, we can do? That is, we want errors of the command to go to the file, but the output of the command to go to the terminal.
$ find /etc ____ file
Options:
- 2>
- <
-
Overall explanation:
2>redirects stderr (file descriptor 2) to file, while normal output (stdout) still goes to the terminal.
Question 5
To redirect both the output and error messages of a command such as du, we can do? Try various things in your Linux shell to see which one works.
$ du /etc ____ file
Answer:
$ du /etc > file 2>&1
>file sends stdout to file.2>&1sends stderr to the same place as stdout, so both end up in file.
Question 6
To redirect the output of a command such as ls to the input of another command such as grep, we can do:
$ ls /etc ____ grep host
Options:
-
- |
- <
Overall explanation:
|is a pipe that sends the stdout of ls into the stdin of grep, so grep filters the output of ls.
Date Formatting
Two useful features in a typical Unix shell are pathname expansion and brace expansion. Given the following output of ls, where all file names are in the format YEAR-MONTH.
2002-01 2002-07 2003-01 2003-07 2004-01 2004-07 2005-01 2005-07 2006-01 2006-07
2002-02 2002-08 2003-02 2003-08 2004-02 2004-08 2005-02 2005-08 2006-02 2006-08
2002-03 2002-09 2003-03 2003-09 2004-03 2004-09 2005-03 2005-09 2006-03 2006-09
2002-04 2002-10 2003-04 2003-10 2004-04 2004-10 2005-04 2005-10 2006-04 2006-10
2002-05 2002-11 2003-05 2003-11 2004-05 2004-11 2005-05 2005-11 2006-05 2006-11
2002-06 2002-12 2003-06 2003-12 2004-06 2004-12 2005-06 2005-12 2006-06 2006-12
Using bash's expansion syntax, complete the following prompts. See Chapter 7, The Linux Command LineLinks to an external site. for more information.
Question 7
To list all the files from 2002, we could use the following expressions (select all that work correctly):
$ ls ____
2002-01 2002-02 2002-03 2002-04 2002-05 2002-06 2002-07 2002-08 2002-09 2002-10 2002-11 2002-12
Options:
- 2002-{01..12}
- 2002-*
20022*2
Overall explanation:
-
Correct:
2002-{01..12}: Brace expansion explicitly generates 2002-01 through 2002-12.2002-*: Globbing matches any filename that starts with 2002-.
-
Incorrect:
2002: Matches only a file or directory named exactly 2002, not the monthly files.2*2*: Globbing matches any name with a 2, then anything, then 2, then anything — it will match all 2002-XX files but also other files with this requirement.
Question 8
To list all the files from the month of December, we could do:
$ ls ____
2002-12 2003-12 2004-12 2005-12 2006-12
Options:
- {2002..2006}-12
*[12]- *-12
- ????-12
Overall explanation:
- Correct:
{2002..2006}-12: Brace expansion generates 2002-12 through 2006-12 explicitly.*-12: Matches any filename that ends with -12, which fits all December files.????-12: Matches exactly four characters, then -12 (e.g., any 4-digit year in December).
- Incorrect:
*[12]: This matches any filename that ends with either 1 or 2.- So
*[12]matches names ending in …1 or …2, like:- 2002-01
- 2003-12
- file2
- So
Question 9
To list all the files from the month of January to June, we could do:
$ ls ____
2002-01 2002-04 2003-01 2003-04 2004-01 2004-04 2005-01 2005-04 2006-01 2006-04
2002-02 2002-05 2003-02 2003-05 2004-02 2004-05 2005-02 2005-05 2006-02 2006-05
2002-03 2002-06 2003-03 2003-06 2004-03 2004-06 2005-03 2005-06 2006-03 2006-06
Options:
2?2[0]{1..6}- *0[123456]
- *-{01..06}
- *-0[1-6]
Overall explanation:
-
Correct:
*0[123456]: Matches any name ending in 01 to 06*-{01..06}: Brace expansion generates -01 through -06, matching all months January to June.*-0[1-6]: Matches any name ending in -01 to -06 using a character range.
-
Incorrect:
2?2[0]{1..6}: Mixed and invalid pattern: {1..6} is brace expansion but attached incorrectly after a glob.
Question 10
Are the following two pipelines equivalent?
$ du -h /etc 2> /dev/null | sort -h > output.txt
$ du -h /etc | sort -h > output.txt 2> /dev/null
Options:
- No, the first pipeline discards the output of du before sorting, while the second pipeline discards the output of the whole pipeline.
- No, the first pipeline redirects the output of du to a file and then sorts the file, while the second pipeline pipes the output of du into sort and then stores it into two files.
- Yes, the pipelines have the same behavior and produce the same output.
- No, the first pipeline discards the error messages of the du, while the second pipeline discards the error messages of sort.
Overall explanation:
- Option 1 is wrong: Redirection doesn't discard "output" (stdout), it discards "errors" (stderr).
- Option 2 is wrong: Neither pipeline involves temporary files or "two files."
- Option 3 is wrong: As explained, the error handling is scoped differently.
- Option 4 is the closest: It correctly identifies that the first pipeline silences du. While the second pipeline technically silences sort, in practice, it fails to silence the errors the user actually cares about (the ones from du).
Unix Shell Variables
Two other important features of a typical Unix shell are variables (i.e., parameter expansion) and command substitution. Using these features, complete the following prompts:
Question 11
To print the value of the HOME variable, we could do:
echo _____
Answer:
echo $HOME
$HOMEexpands to the value of the HOME environment variable, and echo prints it to the terminal.
Question 12
To set the value of the SHELL variable to /bin/bash, we could do:
Answer:
SHELL=/bin/bash
- This assigns the value /bin/bash to the
SHELLvariable in the current shell environment.
Question 13
To compute the md5sum of the ls command while also looking up its location, we could do? See command substitution in the shell. Also look at the where built-in command in the shell.
Answer:
md5sum $(which ls)
- Command substitution allows the output of one command to replace the command name itself on the command line. There are two ways to write this:
- The Modern Way (Recommended):
$(command) - The Legacy Way:
command(using backticks)
- The Modern Way (Recommended):
- If you run
md5sum $(which ls), the shell performs these steps in order:- Subshell Execution: It runs
which ls. - Resolution:
which lsreturns the full path, typically/usr/bin/ls. - Substitution: The shell replaces the
$(...)block with that path. - Final Execution: The shell finally executes
md5sum /usr/bin/ls.
- Subshell Execution: It runs
- Using
wherevswhichwhich ls: Generally returns the first executable found in yourPATH.where ls: Specifically a zsh built-in (or an external utility in some distros) that shows all instances ofls, including aliases and functions.
Question 14
To print all the environment variables in the shell, we could do:
Answer:
printenv
- Both
envandprintenvdisplay all environment variables currently set in the shell. setis even more talkative here
Question 15
What is the key difference between these two commands?
cmd > out.txt 2>&1
cmd 2>&1 > out.txt
Options:
- They are equivalent
- In (1), stderr is discarded
- In (2), stdout is discarded
- In (1), both stdout and stderr go to out.txt; in (2), stderr goes to the terminal (or original stdout) while stdout goes to out.txt
Overall explanation:
cmd > out.txt 2>&1>sends stdout to out.txt2>&1sends stderr to the same place as stdout → both go to out.txt
cmd 2>&1 > out.txt2>&1first sends stderr to the current stdout (the terminal)- then
>sends stdout to out.txt - → stderr still goes to the terminal, stdout goes to the file.
Question 16
Assume you're using the bash shell. If you're unsure, type echo $SHELL in your terminal. Suppose the directory only contains files a1.txt, a2.txt, b1.txt. What does this command print?
echo "*.txt"
Options:
- prints all files in the directory
- error
- expands to matching .txt files
- prints *.txt literally
Overall explanation:
- The quotes
"*.txt"prevent glob expansion, so the shell does not match filenames. echoreceives the literal string*.txtand prints it exactly.
Question 17
What is the key difference between the following two commands?
$ ls *.txt
$ ls "*.txt"
Options:
- The first treats
*.txtas a literal string, while the second expands it - The first performs pathname expansion, while the second passes the literal string *.txt to ls
- Both commands result in an error if no .txt files exist
- Both commands perform pathname expansion and list all .txt files
Overall explanation:
ls *.txt→ the shell expands*.txtto matching filenames before runningls.ls "*.txt"→ the quotes prevent expansion, solsreceives the literal string*.txtas an argument.
Question 18
Assume your current directory contains only the following two files: report_v1.txt, and report_v2.txt. Note that report_v3.txt does not exist in the directory. Which of the following commands will result in an error message (e.g., "No such file or directory") being displayed?
Options:
- $ ls report_v{1,2,3}.txt
- $ ls report_v?.txt
- $ ls report_v[123].txt
- $ ls report_v*.txt
Overall explanation:
- {1,2,3} expands to:
- report_v1.txt
- report_v2.txt
- report_v3.txt
- Since report_v3.txt does not exist, ls is given a non-existent filename and prints an error.
- Why the others do not error:
report_v?.txt→ matches report_v1.txt and report_v2.txt only.report_v[123].txt→ matches 1 and 2; 3 is ignored since no such file exists.report_v*.txt→ matches both existing files.