Dr. Mark Humphrys

School of Computing. Dublin City University.

Online coding site: Ancient Brain

coders   JavaScript worlds

Search:

Free AI exercises


More on Shell




Pipes and redirection in scripts

Remember pipes and redirection on command line.

  

What do programs know about the pipe they are in?

Programs can detect if output going to screen or not.
ls           (gives multi-column output)
ls > file    (gives single-column output)
ls | prog    (gives single-column output)
You can detect if output is going to terminal, file or pipe, and adjust output accordingly.
Shell script to detect where output is going:

if [ -t 1 ]
then
 echo stdout
else
 echo pipe or file
fi

Test it:

prog
prog | cat
prog > file



Arguments and returns (more)


$1           1st argument 
$*           all arguments  

$0		name of prog
$#		no. of args

shift		shift args leftwards 
		this is useful if you want to remove some of the first args, then "shift" a couple of times,
		and then do "for i in $*" with the remaining args
		e.g. grep (switches) (string) file1 ... filen

exit 20		exit with a return code  

$?		return code of last prog executed
		e.g. quiet grep: 
		 grep > /dev/null 
		and then check $?
		though grep may have -q (quiet) option anyway


Environment variables

Like global vars for all programs.
Note any environment vars that are declared within a program are local to that program only.


env
printenv
set 			may display shell functions too


var=value               set environment variable
                        N.B. no spaces!
echo var                print the string "var"
echo $var               print value of environment variable


echo $HOME              get into the habit of using these
                        instead of the actual hard-coded values,
                        - makes scripts more portable 
                        e.g. Einstein automatic marking needs $HOME not your actual home dir 

echo path is $PATH
echo $USER




uname and arch


uname          # show hardware, OS, etc.

arch           # same as "uname -m"

hostname         



Advanced example

Example of using arch in config files.
  1. Over time, I have shared the same set of Unix/Linux files across a number of Unix/Linux systems running on different hardware.
  2. The shell scripts are generally not a problem. They tend to run unchanged on all the platforms. The problem is binary executables.
  3. I collect binary executables for each platform, but keep them in separate directories underneath the   $home/bin directory.
  4. Then at login I set the path to automatically include the correct directory.
    e.g. On my C shell system I put this in the .cshrc file:
    set path = ( $home/bin/`arch` ... )
    
  5. Recall backquotes



Strings and echo


echo                    print something on screen, followed by new line
echo -n                 print with no new line


printf                  print with no new line
printf "\n"             print with new line


On some platforms, echo -e exists (interpret special backslash chars)
On DCU Linux: 

echo -e "\n text \n\n"        print multiple new lines

Two types of quotes


echo "string"
echo 'string'

	It is useful to have 2 choices for string - single quote and double quote.
	If using one for something else, surround with the other.
	e.g. To search for single quote in file:

	grep ' file        syntax error (why?)
	grep "'" file      surround with quotes and it works
	grep '"' file      to search for the double quote itself


The two types of quotes are not equal:

echo "--$HOME--"       --/users/group/humphrys--
echo '--$HOME--'       --$HOME--
echo '--'$HOME'--'     --/users/group/humphrys--



File wildcards


*                       all normal (non-hidden) files
.*                      all hidden files

 "Hidden" in the sense that tools like ls won't list them by default.
 You can write your own tools of course to always list them by default.
 Not actually hidden in the security sense.

 Done for convenience not strict security, like write-protecting your own files
 (which is itself a kind of security since it stops some accidents).
 Doing things to  *  like  rm *  won't affect the  .*  files.



Q. Even on a single-user system, why separate OS files from user files?



echo *                  echo all files
echo f*                 all files beginning with f
echo */*                files in next layer
*/*/*                   etc.

Important to realise it is the shell that interprets "*" and passes the result to echo or ls or your program. It is not actually echo or ls itself that parses it.
grep string *

# grep does not understand *

# but that's fine because grep does not actually RECEIVE *
# what happens is:
# the shell EXPANDS * to a list of files and passes these to grep
# so grep actually receives:

grep string f1 f2 .. fn
To see that it is the shell that expands it, assign it to an environment variable. Try these:

echo *
echo "*"

x=*
echo $x
echo "$x"

x="*"
echo $x
echo "$x"
 
x=`echo *`
echo $x
echo "$x"


Q. Why have the shell interpret "*"? Why not just pass "*" as argument to progs?




ancientbrain.com      w2mind.org      humphrysfamilytree.com

On the Internet since 1987.      New 250 G VPS server.

Note: Links on this site to user-generated content like Wikipedia are highlighted in red as possibly unreliable. My view is that such links are highly useful but flawed.