CSCI 344
Intermediate Bash Scripts
Lab 5
Write the following bash scripts. You may use the Internet as a
reference for bash script syntax and as a reference for UNIX/Linux
commands (such as wc and tail), but you may not search for
solutions to these problems--that would completely defeat the purpose
of doing these exercises.
When you complete one of the scripts, notify me and I will come watch a demo and give you credit for completing it.
Here is a link to the O'Reilly's Learning Bash. Note: this link only works from computers in the csuchico.edu domain.
You may use any UNIX/Linux command or utility to solve these problems.
1) (weight 1) Write a
script that looks through all the directories in $PATH and finds all
matches to the given command. Then prompt the user using a select
statement for which one of these commands should be run:
$ run ls
1) ./ls
2) /bin/ls
run command? 2
lines ls prompt run src
$
Hint:
use lab4::1 as a starting point.
Instead of printing all the matches, put them into a string and
pass this string to the select statement.
When checking to see if a variable is null [ -z $cmds ] if
$cmds has the form "/bin/ls:/usr/bin/ls" and the IFS=:, the [ ] will complain
that you have too many arguments. You can fix this by quoting the
$cmds: [ -z "$cmds" ].
2) (weight 1) Write a version of cat using the bash read command.
If the user specifies a valid file on the command line (it is a
regular file and you can read it) use that file. If not,
prompt the user for a valid file (echo -n does not print the newline).
Keep prompting the user until a valid file is entered.
$ mycat
enter valid file? asdf
enter valid file? qwer
enter valid file? z
one - first line
two
three
four
five - last line
$
Hints:
A string can be read into the variable
filename using the following syntax:
read filename
Assuming that the variable filename contains the name of a valid file,
the entire file can be read one line at a time using the following
syntax:
while read line; do
echo $line
done < $filename
The
read line reads the next
line of the file into the variable line. The "< $filename"
redirects the input of the while loop to be the file named by the
variable filename.
3) (weight 4) Write a script
that counts the lines of all files in a given directory and reports the
total by extension.
$ lines ~/src/gpl
cpp: 4196
h: 3959
l: 192
y: 1561
$
Ignore files that do not have an extension (that is, they don't have a .).
If a file has the form <string1>.<string2>. ... .<stringN> assume that stringN is the extension.
If the argument is not a directory or if no argument is given, issue the following message and exit with an error status
$ lines foo
Usage: lines directory
$
Hints:
The command wc counts the lines in the given files. When passing multiple files to wc the last line contains a total. When passing one file to wc, the last line can also be thought of as the "total." The command tail can help you with this.
In my solution I first find all the different extensions in the directory. Once you know all the extensions you can use wc $dir/*.$cur_extension to count all the files.
When checking to see if a variable is null [ -z $extensions ] if
$extensions has the form "cpp:h:y" and the IFS=:, the [ ] will complain
that you have too many arguments. You can fix this by quoting the
$expressions: [ -z "$extensions" ].
In lab I suggested you could use grep to find if you already have seen
the pattern. Since egrep recognizes the "|" for or, it is a
better choice. However, it is difficult to get it to work.
After an hour I gave up. It is much easier to use a loop
and loop through the extensions you have already seen than to use
egrep. Don't agree? try a directory with a.cpp and b.pp and
c.p and d.c.