CSCI 344
Intermediate Bash Scripts
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.
Here is a link to the O'Reilly's Learning Bash.
Note: this link only works from computers in the csuchico.edu
domain and only works sometimes (maybe it has to do with the phase of
the moon).
Unlike the previous Bash assignment, 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 your answer for question 1 in the
basic_bash_scripts assignment 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.