START OF WEEK 2 of Linux

<<< FILE TIMESTAMP >>>
  -The up to date file is: /usr/courses/cps393/dwoit/courseNotes/
  -If you are viewing your own copy, check it is up to date
  -If you are viewing from a link in the Course Outline, be aware it may be outdated.



<<< PIPES >>>

a pipe  |  connects stdout of one command to stdin of another

e.g., 
  cd /usr/courses/cps393/dwoit/courseNotes/Programs/linux
  ls |  more             # lists all files in current dir, one
                         # screen at a time
  ls -lt | head          # lists the 10 most recently modified
                         # files in this dir

  ls -lt | head >outfile # prints output into file outfile

  last | head            #show first 10 logins on this machine since wtmp
                         #last output has oldest at end. 

  #print line 54 of AlanTuringBio80 
  cat AlanTuringBio80 | head -54 | tail -1 

  #print line 54 in reverse character order
  cat AlanTuringBio80 | head -54 | tail -1 | rev
   

  #print the 18-20th-last lines of AlanTuringBio80 
  tac AlanTuringBio80 | head -20 | tail -3 | tac
  cat AlanTuringBio80 | tail -20 | head -3 


pipes contribute to shell`s usefulness and flexibility
  -no need to create new commands to perform a task--can combine
   existing commands to perform more complex tasks
  -no need for "temp" files


<< TEE COMMAND >>

saves the data passing through the pipe
writes stdin to stdout AND to a given file

e.g.,   changing: cat AlanTuringBio80 | head -54 | tail -1
        to:       cat AlanTuringBio80 | head -54 | tee first54 | tail -1
        the same, but ALSO saves first 54 lines in file first54


<<< GLOB CONSTRUCTS, METACHARACTERS AND OTHER SPECIAL CHARACTERS >>>


?  *  [   ]              #some glob constructs
                         #man bash search for: Pathname Expansion

saves typing,  time
encourages good naming conventions

when shell encounters a glob construct: 
  -first expands construct to matching entries
  -then does resulting command 

*       string of characters (incl. null string)
?       single character
[...]   single char from set of chars within the brackets

e.g., assume /home/dwoit has 7 files:  

                lab1.jav lb2.jav new.c pie.c prog1.c prog2.c top.c 

        /home/dwoit> ls *.c
                                new.c pie.c prog1.c prog2.c top.c
        /home/dwoit> ls *
                                lab1.jav lb2.jav new.c pie.c prog1.c 
                                prog2.c  top.c
                
        /home/dwoit> ls prog?.c
                                prog1.c prog2.c
        /home/dwoit> ls p*.c
                                prog1.c prog2.c pie.c
        /home/dwoit> ls ???.*        
                                lb2.jav new.c pie.c top.c
        /home/dwoit> ls prog[123].c
                                prog1.c prog2.c
        /home/dwoit> ls prog[abc].c     #since no expansion, uses literal string
                                ls: cannot access 'prog[abc].c': No such file or directory
        /home/dwoit> ls [m-s]*          # all files starting with one of these:
                                        # m n o p q r s
                                new.c pie.c prog1.c prog2.c

        [1-58]          matches any single char in 1 2 3 4 5 8
        [A-Za-z]        matches any single char in A,B,...Z,a,b,...z
                             systems may differ depending on $LC_COLLATE
                             or globalasciiranges, etc.
                             see man bash search for Pattern Matching
        [!ABC]          matches any single char *except* A, B or C
        [!a-z0-4]       matches any single char *except* a,b,...z,0,1,2,3,4
                        (in some bash, ^ can be used instead of !)

        These Character Classes can be used within [ ] 
        [:alnum:]  [:alpha:]  [:blank:]  [:cntrl:]
        [:digit:]  [:graph:]  [:lower:]  [:print:]
        [:punct:]  [:space:]  [:upper:]  [:xdigit:]

	note    [:upper:]   is A-Z
	so     [[:upper:]]  is [A-Z]

        /home/dwoit> ls [[:upper:]]* matches files whose name starts
                                     with an upper-case letter A-Z

        What is the difference between these?:
        ls [[:upper:][:upper:]]*
        ls [[:upper:]][[:upper:]]*

        First one matches files whose name starts with an upper case letter
        Second one matches files whose name starts with two upper case letters

--------------------------------------------------------------------------
Optional.
If you want to change the collate order in the shell to ASCII you can execute
shopt -s globasciiranges
Once you do that, then the ordering is A-Za-z (see man ASCII for order), and
a command such as ls [A-Z]* will list only those files starting with an 
upper-case letter, and ls [a-z] only those starting with lower-case letters.
You MIGHT already have globalasciiranges set to on. You can see what bash 
options are set by executing: 
echo $BASHOPTS
If you see globalasciiranges in the list, then it`s on for you. If it`s not on,
then do the shopt command above to turn it on.
globasciiranges only pertains to USING globs (like in ls commands), but not to the
order that ls displays files. If you want to change the order of displayed files,
you still have to change LC_COLLATE, as follows...

What gets matched in a range [], depends on the value of LC_COLLATE 
(use the locale command to display your LC values).
Some years, students have LC_COLLATE set to "en_CA.UTF-8". This collates 
as AaBbCc...Zz.  That is why files will be listed in that order, e.g.:
   Art bart  Mart  zart
If you want to collate according to ASCII order (man ASCII for order), which has, 
among other things, A-Z before a-z, you can set LC_COLLATE="C".
Then the above files would be listed as: Art Mart bart zart
You can change it by putting export LC_COLLATE="C" in your .bashrc and 
.bash_profile (and logging in again). Or, you can change it temporarily, just for 
one command by setting it just before the command; for example: 
LC_COLLATE="C" ls -la
Or you can change it in the current shell by typing
export LC_COLLATE="C"
It will stay in effect in that shell until you exit.
--------------------------------------------------------------------------


Other special characters:

\       protects the character following it from being expanded
\       at end of line, means continued on next line (see program trump_born.sh)
;       separates commands: mkdir newDir ; cd newDir ; touch newFile
~       your home directory name  (/home/dwoit for prof)

~usr    the home dir of user with userid "usr"
~-      your previous working dir  (note in bash  cd - same as cd ~-)
~+      your current working dir

      /home/dwoit>  echo list java files by: ls \*.jav
                    list java files by: ls *.jav
      /home/dwoit>  echo list java files by: ls *.jav
                    list java files by: ls lab1.jav lb2.jav

     from any dir,  ls ~    lists your home dir (/home/dwoit for prof)
     from any dir,  cd ~/bin changes into dir /home/dwoit/bin for prof

toggle between 2 dirs with "cd ~-" (or with "cd -" in bash)
      /home/dwoit>     cd bin
      /home/dwoit/bin> cd -
      /home/dwoit>     cd -
      /home/dwoit/bin>

execute a pgm called myprog in dmason`s dir cps209
      /home/dwoit>    ~dmason/cps209/myprog #assuming correct perms:
                                            # x on dirs, and 
					    # x  on myprog (if a compiled program), or
					    # rx on myprog (if a shell program)
      /home/dwoit/bin>   echo my working dir is ~+
                         my working dir is /home/dwoit/bin


could use quotes instead of escape character \
all these print this on stdout: list the java files in this dir by *.jav

      /home/dwoit>  echo list the java files in this dir by \*.jav
      /home/dwoit>  echo list the java files in this dir by "*".jav
      /home/dwoit>  echo list the java files in this dir by "*.jav"
      /home/dwoit>  echo "list the java files in this dir by *.jav"


<< PATTERNS AND REGULAR EXPRESSIONS IN SHELL >>


The extended globs below require bash option extglob to be set.
To see which shell options are set:
echo $BASHOPTS
If extglob is not set, set it by:
shopt -s extglob


 *(exp)           0 or more occurrences of exp
 +(exp)           1 or more occurrences of exp
 ?(exp)           0 or 1 occurrences of exp
 @(exp1|exp2|...) exp1 or exp2 or ...
 !(exp)           entries that do NOT match exp

e.g.,
 if you had files in the current dir:
     A  Ax  Axxx  Axxxx  Ay  X  X.bak  x  xx  xxxx
 then 
  shopt -s extglob   if necessary
  ls A*(x)           prints A Ax Axxx Axxxx
  ls A*(xx)          prints A  Axxxx
  ls A+(x)           prints Ax Axxx Axxxx
  ls A?(x)           prints A Ax
  ls X?(.bak)        prints X X.bak
  ls @(*xx|*ak)      prints Axxx  Axxxx  X.bak  xx  xxxx
  ls !(@(*xx|*ak))   prints A  Ax  Ay  X  x

Note: See "man bash" and search for "Pattern Matching"
      for help on globs, patterns, etc.



HMWK: How would you list all file/dir names that: 
1. contained the letter "e"; 
2. had a total of 7 characters and no extension; 
2a. are 7 characters long;
3. had 3 character extensions;  
3a. had 3 character alpha-numeric extensions;
4. contained the word "tst" *somewhere* in the name; 
5. started with the letter "A" and contained a dash (-);
6. are at least 2 characters long and do not have the following letters
   anywhere in the first 2 characters: a,b,c,f,h,x,y,z
7. end in .ex with an optional c at the end
8. are not java or text files (do not end in .jav or .txt)
9. end in a : followed by a digit from 2-8 followed zero or more
   digits.

EOH 1


<<< INTERACTIVE SHELL USE >>>
 
-typing on command line
-one-time task
-prototyping


<<< SHELL PROGRAMS (SHELL SCRIPTS, SHELLS) >>>

-executable file containing shell commands
-can run like a program (type its name on command line)


Why?
  -task is complex
  -repeat it later
  -repeat it in different context (arguments)

Typically file containing shell program has .sh suffix
but in cps393 we sometimes omit suffix


#!/bin/bash
#source: showSource.sh
#shell program to list all java and c files in current directory
echo -n "Current directory is: "
pwd
echo "C files are:"
ls *.c
echo "Java files are:"
ls *.jav
exit 0

To run:
  Make sure it is executable (x permissions for user running it), then
  type its name on command line after ./

  If you own the program, need rx perms for user
  If you don`t own it,    need rx perms for other


  > cd /usr/courses/cps393/dwoit/courseNotes/Programs/linux
  > ls -l showSource.sh
  -rwxr-xr-x 1 dwoit cps393 203 Jul  2 14:57 showSource.sh
  > ./showSource.sh
  Current directory is: /usr/courses/cps393/dwoit/courseNotes/Programs/linux
  C files are:
  blah.c
  Java files are:
  blah.jav  color.jav  pgm1.jav  TextStackViewer.jav  ttt.jav  VisibleStack.jav  xyz.jav
  > 


  > cd     #for prof
  > cp /usr/courses/cps393/dwoit/courseNotes/Programs/linux/showSource.sh showSourceCopy.sh
  > ./showSourceCopy.sh
  Current directory is: /home/dwoit
  C files are:
  ls: cannot access '*.c': No such file or directory
  Java files are:
  DAC.jav skipList.jav

----------------------------------------------------------------------------------
Optional:
 To turn on syntax highlighting in vim (if not already on):
   -when in vim editing a shell program
      go into command mode (hit esc a few times)
      type   :syntax on
      behold the nice colors
  If filename specifies file type, vim uses that highlighting, e.g., 
  vim understands xyz.c is a C program file and hilights accordingly.
  If vim cannot figure it out (e.g., C file named xyz), then force it by
  telling vim to set the filetype, as in
  :se ft=c
  To highlight a bash program use :se ft=sh
----------------------------------------------------------------------------------


Shell Script Arguments:
            $1  $2  $3  etc.
            $0  name of shell pgm
            $#  the number of args passed
            $@  lists args as one string: "arg1 arg2 ..."
            $*  lists args as separate:   "arg1" "arg2" ...

#!/bin/bash
#source: prnargs.sh
#shell pgm to print out its first 2 args
echo The first argument is:  $1
echo The second argument is: $2
echo dollar zero is: $0
exit 0


  /home/dwoit>  cp /usr/courses/cps393/dwoit/courseNotes/Programs/linux/prnargs.sh .
  /home/dwoit>  ./prnargs.sh  "Hello there" world
  The first argument is: Hello there 
  The second argument is: world
  dollar zero is: ./prnargs.sh


  Note: spacing in program differs from spacing in output 
  Why?  echo squeezes multiple whitespace to single space


  Could line up spacing with quotes or tabs: 
       echo "The first argument is:  $1"
       echo "The second argument is: $2"

       echo -e "The first argument is:\t$1"
       echo -e "The second argument is:\t$2"
    

  Could leave out the ./ if current dir in your path.
      e.g.,    /home/dwoit> prnargs.sh   (instead of ./prnargs.sh)
      If it says prnargs.sh "not found" can fix by adding the current dir to your path
         e.g., in your .profile or .bash_profile or .bashrc at the end put:
           PATH=$PATH::
           export PATH
         Must login again for it to take effect.
         Now, whenever you login, current dir always in path.


<<< FILTERS >>>

filter: refines or transforms its input to produce (usually different) output
most shell commands are filters. 

             stdin -------> filter --------> stdout

e.g.,  more <file1
         transforms sequence of characters from file1 (its input) 
         into the same sequence but with  pagination
       rev 
         transforms each stdin line to line in reverse
         (remember ctrl-d to end)
       uniq 
         filters out duplicate lines

Some filters filter input from either stdin or file(s)


<< GREP  (GLOBAL REGULAR EXPRESSION PRINT) >>
        (globally search for a regular expression and print it)


grep string filename(s)
                string:         the string to search for
                filename(s):    one or more files to search in
                result:         displays lines of file(s) 
                                        that that contain string
grep string     
                searches stdin instead of file(s)
                sends to stdout lines of stdin that contain string
                ctrl-d "ends" stdin when you are typing on keyboard
                                

e.g.  grep  'applet' lab1.jav lab2.jav
        sends to stdout (screen) those lines of files lab1.jav and
        lab2.jav that contain the string applet
        /home/jchan>    grep 'applet' lab1.jav lab2.jav
                                lab1.jav:       applet.init();
                                lab1.jav:       applet.start();
                                lab2.jav:       applet.num=6;

e.g. Which course notes mention touch? 
     Try searching for 'touch' in all u?.txt files:

     /usr/courses/cps393/dwoit/courseNotes> grep 'touch' u?.txt
     u1.txt:     ls, cd, pwd, cat, more, cp, rm, mkdir, rmdir, mv, wc, touch,
     u1.txt:touch   creates file(s) or updates modification time(s)
     u1.txt:        /home/dwoit> touch abc def ghi
     u1.txt:        /home/dwoit> touch f1 f2 f3 f4
     u2.txt:;       separates commands: mkdir newDir ; cd newDir ; touch newFile


Note: single quotes are good for now. Once we study variables, you
      may have reason to use double quotes around the search string.


Options:
-i  ignore case of search string
-v  print lines *not* matching search string
-x  search string must match ENTIRE line 
-w  search string must match a whole word
-l  print only names of files that match, not individual lines
   (man grep gives all the options)

Regular Expressions:
The grep search string above can be specified as a regex, i.e., 
    can contain metacharacters for pattern matching

.       any character, except newline (like ? in glob)
*       0 or more repetitions of previous character (unlike glob)
^       beginning of line
$       end of line
[...]   any character inside the brackets (like glob) 
[^...]  any character not inside the brackets (like ! in glob)
\{m\}   exactly m repetitions of previous character
\{m,\}  at least m repetitions of previous character
\{m,n\} any number of repetitions of prev char between m and n inclusive 
\<      beginning of word
\>      end of word
        remember to quote these as in: grep '\<theWord\>' a_file
\(str\) group string str into a substring

To match an actual metacharacter such as . protect it: \.

e.g.,  searching in file fname (and later stdin): 
grep '^Assignment' fname    # lines starting with Assignment
grep -v '^Assignment' fname # lines not starting with Assignment
grep 'Assignment$' fname    # lines ending with Assignment
grep 'd.g' fname            # lines containing dag, dbg, dcg, d0g, d1g, etc
grep 'su*m' fname           # lines containing sm, sum, suum, suuum, etc
grep 'suu*m' fname          # lines containing     sum, suum, suuum, etc
grep '\<so\>' fname         # the word so (vs. social, absolute)
grep '[A-Za-z][A-Za-z]*' fname  # lines containing ANY alpha string (no blank
                                # lines, no lines with only digits, etc)
grep '^[A-Za-z][A-Za-z]*$' fname  # lines containing ONLY alpha characters
grep 'xyz\.[^ ]* '         # lines containing string xyz followed by a dot
                           # followed by 0 or more non-spaces, then one space
                           # e.g., "xyz. " "xyz.w "  "xyz.ta "  etc
grep 'xyz\.w\{2,3\}X'      # lines containing xyz.wwX or xyz.wwwX
grep 'A\(bc\)\{2,3\}D'     # lines containing AbcbcD or AbcbcbcD
grep -x "abc"              # lines that contain exactly and only abc


Extended Regular Expressions:

use grep -E  (or egrep, but deprecated) 

|       OR 
+       1 or more repetitions of previous character 
( and ) do not need escaping (substring) 
{ and } do not need escaping (repetition)
\n      backreference: \1 replaced by substring 1, \2 by substring 2, etc

e.g., 
grep -E 'dog|cat|bird'         # lines with at least 1 of dog, cat, or bird
grep -E '[A-Za-z]+'            # lines with at least one alpha char
grep    '[A-Za-z][A-Za-z]*'    # same as above if no -E option
grep -E 'xyz\.w{2,3}X'         # lines containing xyz.wwX or xyz.wwwX
grep -E 'A(ab){2,3}D'          # lines containing AababD or AabababD
grep -E 'A([aei]+)B(.*)C\2\1'  # lines containing strings such as:
                               # AieiBxyzCxyziei  or  AiBCi etc


See "man grep" and search for "REGULAR EXPRESSIONS" for help on them


HMWK: In the shell, is grep '[A-Za-z][A-Za-z]*' fname  the same as
grep -i '[A-Z]*' fname ? Why or why not?
Why do you think "\<" and "\>" are used instead of simply "<" and ">" for 
beginning/end of line? 
For questions 1-6 below, write a different shell program for each. 
1. list all lines in file fname containing the string "dog"; 
2. list all lines in fname containing the word "dog"; 
3. list all lines in fname containing the string "dog" at the beginning of 
   a line; 
4. list all lines in fname containing the word "dog" at the beginning of a line.
5. list all lines in fname containing exactly 6 "a"s in a row.
6. list all lines in fname containing one or more words that start with 93 and
   end in a sequence of any number of W (not 0)
7. Give 2 different grep commands that will list lines of fname that 
   end in a lower-case vowel. 
8. Use the man page to find the option of grep that shows the matched string
   in a different color. Try it.
9. How would you change your program for #1 above so that instead of doing grep
   directly from the file, it cat`s the file, then pipes that to grep which
   greps from stdin?
10. Print the first 3 lines of AlanTuringBio80 that contain the string 'machine' 
   in any case. Use grep, pipe(s), and head.

EOH 2


<< FIND  (LIST ALL FILES AND DIRS MEETING CERTAIN CRITERIA) >>


   e.g., this lists all java files in portion of the filesystem 
         rooted at /home/dwoit: 


    find /home/dwoit -name "*.jav" 
          ^           ^           
          |           |          
          |           |         
          |           match any entry with name *.jav (glob)
          dir to begin search (whole subtree of filesystem starting here)


     find . -type f          # only FILES in filetree under current dir (.)
     find . -type d          # only DIRECTORIES in filetree under .

     find /usr -name tali 2>/dev/null        #if takes too long ctrl-c and... 
                                                
     find /usr/[!c]* -name tali 2>/dev/null  #eliminate /usr/courses
                                             #or use -prune (see below)

     find . -type d -perm -g+r,u+r   # dirs readable by BOTH owner and group 
     find . -type d -perm /g+r,u+r   # dirs readable by EITHER or BOTH owner & group
     find . -type d -perm /a+w       # dirs with at least one write bit set
     find . -type d ! -perm /a+x     # dirs having no x perms at all
     LOTS of ways to specify perms--see man find

     cd /usr/courses/cps393/dwoit/courseNotes/Programs/c
     find . -name "m*.c"     #get matches from ./c1 ./c2 ./c3 and ./c4
     #eliminate ./c2 from the search using -prune:
     find . -name c2 -prune -o -name "m*.c" -print  
                             #-o means "or". 
                             #need -print to print the one that recurses
                             #otherwise dir name ./c2 itself is still printed
                             #-print is normally implicit. However, if explicitly
                             # include it, then only commands WITH -print get printed
                             # and not any other commnds (just right-side of -o and 
                             # not left side, since left has no -print)
     #could eliminate /usr/courses from tali search using -prune
     find /usr -name courses -prune -o -name tali -print 2>/dev/null


   LOTS of options to find. Some useful ones are:
   -newer xyz   #list entries that have been modified more recently than file xyz
   -maxdepth 1  #descend only 1 level down directories (can use any integer)
                                  
   Why quote arguments to -name?:
      If argument has unquoted glob constructs, bash EXPANDS it first
      and then sends result to find. But that`s not what we wanted:
      /home/dwoit/testdir> ls
                           abc.c  dir1/  dir2/  dir3/
      #correct way to find all entries matching name pattern a*.c
      /home/dwoit/testdir> find . -name 'a*.c'   
      ./dir1/a1.c
      ./dir1/a2.c
      ./dir2/arc.c
      ./dir3/am.c
      ./abc.c
      #INcorrect way. Expands to: find . -name abc.c 
      /home/dwoit/testdir> find . -name a*.c
      ./abc.c
      /home/dwoit/testdir>  

     
HMWK:  
1. Use the "find" command to list all entries in directory /bin 
that start with the letter "m".  
2. What would happen if we did not put 
a name such as "*.jav" in quotes in the find command? Make sure you have 
some .jav files in your directory and try it out.
3a. Look at the man pages for "find" to determine what the option 
"-mtime" does in the find command. Then...
Figure out a sequence of commands (involving find, temporary files, and grep) 
to display those FILES in the current directory whose contents were
changed within the last 24 hours and whose names contain the string "tst".
3b. How would you do 3a using a pipe and no temporary files?
4a. Make a shell program to do question 3a above. Call your program tstRecent
Your program should delete any temporary files it creates.
Test it to make sure your program works.
4b. Rewrite your program from 4a to use pipes instead of temp files.
5. Use the man pages to find out how find`s -maxdepth option works. Use 
-maxdepth 1 to list all entries in the given directory only (not the whole 
filetree under it)



<< MORE ADVANCED HEAD, TAIL OPTIONS >>

Saw previously:
  head -2 f1 f2 f3  #sends to stdout first 2 lines of f1, f2, f3 
  head -19          #sends to stdout first 19 lines of stdin 

option -n-X for head and -n+X for tail:

  # sends to stdout all lines of f1 starting at line 3
  tail -n+3 f1    

  # sends to stdout all but the last 2 lines of f1
  head -n-2 f1 

  #print list of recent logins minus the final 2 lines
  last | head -n-2          #last logins without the final 2 lines


  #note, tail -n-3 is same as tail -3
  #      head -n+2 is same as head -2
  

(options are in man pages. Lots for tail. )

HMWK:  
The following program displays, on stdout, line 6 of file 
/usr/courses/cps393/dwoit/courseNotes/vimSummary.txt:

#!/bin/bash
#program to print line 6 of vimSummary.txt
head -6 /usr/courses/cps393/dwoit/courseNotes/vimSummary.txt | tail -1 

Copy the code into a file called showline and modify it as follows:
      Make it able to show ANY line of ANY file, with
      line and file given as a command line argument, as in:
      ./showline 5  myfile  #to show line 5  of file myfile
      ./showline 54 dog     #to show line 54 of file dog


<< CUT, PASTE COMMANDS >>

cut     extract specified input columns
paste   combine input columns

both take input from stdin or files

cut -c8 myfile  # outputs 8th column of each line of myfile
cut -c5-7,25-   # outputs columns 5,6,7,25... of each line of stdin
cut -f2 myfile  # outputs second field of each line of myfile 
                #         (assumes fields delimited by one tab)
cut -d' ' -f3   # outputs field 3, fields delimited by one space

paste f1 f2     # linei to stdout contains linei of f1 followed by
                # a tab followed by linei of f2
paste -d' ' f1 f2  # uses single space instead of tab

 
Aside:
   If you have things separated by tabs in a file, and want the tabs
     converted to spaces, use the command: expand
   cat -A will show tabs, newlines, etc. (see man page)


HMWK:
(1) Create a file called stdnt-file with last-names in column 1,
first-names in column 2, id numbers in column 3, userids in column 4.
Populate your file by adding some fake students.
What combination of commands (and possibly temp files) can you use
to create a file, stdnt-ids, that contains only the id numbers and
userids from stdnt-file?
(2) How can you combine commands (and possibly temp files) to create
another file, stdnt1, that contains only the first and last students
in stdnt-file?
(3)
Display the time userid dwoit (or whoever you want) logged in on some
connection.  You will find the "who" command useful. It tells you who
is logged in, and what they are doing. For an explanation do:  man who
Note that "dwoit" (or whoever) will likely have multiple entries (one
for each "terminal" connection), so your output may have multiple lines.


Some shell programs:

#!/bin/bash
#source profs.sh
#prints names of profs.sh logged in
who | grep dwoit | cut -c1-8 | uniq
who | grep eharley | cut -c1-8 | uniq
who | grep aabhari | cut -c1-8 | uniq
who | grep -w mes | cut -c1-8 | uniq #string in other userids
exit 0
#or who | grep -Ew "dwoit|eharley|mes" | cut -c1-8 | sort -u


Try this: use any of ls, cut, sort, uniq, head, tail and pipes
to get a listing of all the different GROUPS entries belong to 
in the current directory. List each group only once.


#!/bin/bash
#source prof1.sh
#prints names of a prof logged in
#name supplied as command line argument
who | grep -w $1 | cut -c1-8 | uniq

See what happens if you use prof1.sh without an argument.
How do you fix it? (hint: use double quotes in grep)



Note 2 pipes and line continuation character \

#!/bin/bash
#source: trump_born.sh
echo "Donald Trump's Birthday: "
lynx -dump "https://en.wikipedia.org/wiki/Donald_Trump" 2>/dev/null | \
      grep "Trump.*born" | head -1
echo ""
exit 0



HMWK: Use various commands and pipes to do the following (do not
use any temp files):
1. List, in long form, all those files in your home directory that have
read, write and execute perms for you, and whose name contains the
string "txt".
2. Do the above question again, but list in short form
(just the file names.)
3. List any lines in the first 10 lines of a file, myf, that contain the
word "dog". (you should create different versions of myf to test your
commands.)
4. Find all lines of file, myf, that contain all the words "cat", "dog"
and "mouse", in any order, and start with the letter "A".
5. List all the files in your home dir that contain the string "so"
somewhere within them. Next, just list the *number* of files in your
home dir that contain the string "so" (you should use, among other
commands, the command "wc -l", word-count (lines option), which you
should look up in the man pages.)
6. Use only ls, grep, cut, pipes to answer this question. What sequence
of pipes and commands could you issue from your home dir
to list, in alphabetical order, the absolute path names of all the
directories in your file system (if you NEED to, use the sort command.)
7. List the names of any subdirectories of your home directory that have
rwx permissions for user and group, and no permissions for
others--note: list just the directory names in short form (the names only.)
8. List just names of all files/directories that have no extension;
9. List just names of all files/directories that contain no vowels at
all.
10. Write a shell program called nw.sh that takes either zero or one
 command line arguments.
 nw.sh with no arguments should print out the 10 newest (most recently
 modified) files/dirs in the current directory.
 nw.sh -n  (nw.sh with one argument, -n) prints out the n newest
 files/dirs in the current directory.
 e.g., nw.sh -3  prints out the 3 most recently modified files/dirs
 If the argument is incorrect, then your program is allowed to
 do unpredictable things!
11. List names in reverse alphabetical order, of directories that have "r"
permissions for "other". (the "reverse" option of the sort command may
be useful.)
12. List in alphabetical order all files in the current directory that have
been edited exactly 3 days ago. Do not list the same file more than once.
(the uniq command will eliminate duplicate lines).



END OF WEEK 2 (UNIX)


May do u2Lab now