-------------------------------- Practice Unix/Linux Questions #3 -------------------------------- -IAN! idallen@idallen.ca Remember to structure your shell scripts with a correct DAT2330 script header and the nine-part format described in the file script_style.txt under Notes. Make sure your script conforms to the script_checklist.txt 1. Write a script that displays one of three different messages depending on the value of the current second of time (as given by the Unix date command): Seconds 00-19 print: Less Code is Better Code. Seconds 20-39 print: If this were easy, everyone would do it. Seconds 40-60 print: *** BINGO! *** Hint: This shell command line prints just the current year: date '+%Y' The man page gives other possibilities (e.g. hour, minute, second). Examples of use: $ date ; ./i.sh Wed Nov 10 04:15:05 EST 2004 Less Code is Better Code. $ date ; ./i.sh Wed Nov 10 04:15:21 EST 2004 If this were easy, everyone would do it. $ date ; ./i.sh Wed Nov 10 04:15:43 EST 2004 *** BINGO! *** 2. Enhance the above script to accept an optional single command-line argument. If the argument is missing, prompt for it and read it from the user. Issue an error message and exit the script non-zero if there are two or more arguments. The user input should be validated to be one of three strings, either "hour", "min", or "sec". Print an error and exit the script if this is not true. Use the input to select whether the script will use the hour, minute, or second field from the date command to print the message. Use the same number ranges as before. Examples of use: $ ./i.sh Enter hour min or sec: junk ./i.sh: Expecting argument of hour min or sec; found 'junk' $ ./i.sh one two three ./i.sh: Expecting one argument: hour min or sec; found 3 (one two three) $ ./i.sh "some junk" ./i.sh: Expecting argument of hour min or sec; found 'some junk' $ date ; ./i.sh hour Wed Nov 10 04:30:19 EST 2004 Less Code is Better Code. $ date ; ./i.sh min Wed Nov 10 04:30:23 EST 2004 If this were easy, everyone would do it. $ date ; ./i.sh sec Wed Nov 10 04:30:49 EST 2004 *** BINGO! *** 3. Change the above script to make it a CGI script that accepts one argument. Since you can't prompt for input in a web server, if there are no arguments on the command line, assume "sec". Make sure all CGI script error messages appear on standard output, not on standard error. BONUS: Only assume "sec" if standard input is not a terminal. If standard input is a terminal, prompt and read input as before. (Hint: See the "tty" command used in shell_read.txt file.) 4. Write a script that counts the number of comment and non-comment lines in a text file. The script takes an optional input file name argument. If there is more than one argument, print an error message and exit. If the argument name is missing, prompt and read the name from the keyboard. If the name given by the user is the null string (no characters in the name), print an error message and exit. If the name is not an existing, readable, plain file, print error messages and exit. If the file has zero size (empty file), print an error and exit. If the type of the file (as printed by the "file" command) does not contain the string "text", print an error message and exit. The two-character pattern "^x", when given to the "grep" command, matches lines that begin with the single character 'x'. Find and count the number of comment lines that start with '#' in the file. Also count the number of non-comment lines. Print a message on standard output using this output template: XXX: file 'YYY' has AAA comment and BBB non-comment lines. Replace XXX with the name of the script. YYY is the name of the file. AAA is the count of comment lines. BBB is the count of non-comment lines. The quotes are required around the file name. If the file has no comment lines, print: XXX: file 'YYY' has no comment lines. If there is at least one comment line and the number of non-comment lines is greater than the number of comment lines, print: XXX: file 'YYY' has more code than comments. 5. Write a script that makes pseudo-English pluralizations. The script needs two values from the user: an integer and a text string: $0 [ number [ string ] ] These two values may be supplied on the command line. If any of the arguments are missing, prompt and read the missing values from the keyboard. If there are more than two command line arguments, print an error message and exit. If any argument given by the user is the null string (no characters in the input), print an error message and exit. Output the string with the letter "s" appended, unless the number is either 1 or -1. Examples: $ ./i.sh 0 dog dogs $ ./i.sh 1 dog dog $ x=2 ; ./i.sh $x "I have $x dog" I have 2 dogs Note that this script knows nothing about the English language; so, it will misbehave on some input, e.g.: $ i=5 ; ./i.sh $i "I saw $i mouse" I saw 5 mouses (WRONG - should say "5 mice") 6. Write a script that sorts three numbers, without using the "sort" command. The script needs three integer input numbers from the user: $0 [ n1 [ n2 [ n3 ] ] ] These three values may be supplied on the command line. If any of the three arguments is missing, prompt and read the missing values from the keyboard. If there are more than three command line arguments, print an error message and exit. The output will be the three numbers in ascending order. You must use a series of IF statements to compare and put the numbers in order; you cannot use the "sort" command. Examples: $ ./i.sh 3 2 1 1 2 3 $ ./i.sh -1 3 2 -1 2 3 7. Write a script that mimics part of the output of the "id" command, without using the "id" command. The script needs one optional input userid from the user: $0 [ userid ] If the userid argument is missing, use the value of environment variable $USER. Locate the password file entry for the userid and extract the numeric uid and gid fields from the file. Do not use the "id" command. In the file /etc/group, count how many lines contain the userid. Output the userid, uid, gid, and the count of the group lines: $ ./i.sh idallen idallen has uid 777 and gid 777 with groups=1 $ ./i.sh news news has uid 9 and gid 13 with groups=1 $ ./i.sh xfs xfs has uid 71 and gid 71 with groups=2 8. Write a script that puts lines in a file until it exceeds a given size. The script needs three input values from the user: an integer line count, an input file name, and an output file name (in that order): $0 [ linecount [ infile [ outfile ] ] ] These three values may be supplied on the command line. If any of the three arguments is missing, prompt and read the missing values from the keyboard. If there are more than three command line arguments, print an error message and exit. If any argument given by the user is the null string (no characters in the input), print an error message and exit. If the integer line count given by the user is not greater than zero, print an error message and exit. If the input file name is not an existing, readable, plain file, print error messages and exit. If the input file file has zero size (empty file), print an error and exit. If the type of the input file (as printed by the "file" command) does not contain the string "text", print an error message and exit. If the output file exists and has a size bigger than zero, print an error message and exit. If the output file exists, rename it to have a ".bak" extension. While the count of lines in the output file is less than the given file size, concatenate the current date and the contents of the input file over and over into the output file. Exit the script non-zero if the concatenation fails. (Use the quick-test "||".) Print the number of lines in the output file. [...more script practice to come...]