JP Vossen on 23 Dec 2009 10:22:53 -0800


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] Easy Bash Scripting Question


> Date: Wed, 23 Dec 2009 07:45:16 -0500
> From: Casey Bralla <MailList@nerdworld.org>
> 
> I've written a bash script and I find that the commands don't normally echo to 
> the screen, so I can't follow along with the script.
> 
> for example:
> 
> #!/bin/bash
> cp file1 file2
> mkdir /directory1
> cd /directory1
> rm *
> cd ..

Ouch.  Mark had some excellent points about the fragility and potential 
danger of this example as-is.

At *least* hard-code the path for rm (rm /directory1/*), but better yet 
is to check error codes.  The trivial way is to add 'set -e' at the 
second line.  That will cause the script to exit if any command fails. 
Thatg way it will stop as soon as it breaks, but the down side is you 
won't know quite why.

A sillier way to do the same thing would be to chain the commands 
together using '&&' but that's more error prone when you later add to 
it, and harder to read.  It sometimes makes sense, with something like:
	cd foo && rm bar*

You can check an individual command like so:
mkdir /directory1 || {
     echo "Unable to create /directory1, error code: $?"
     exit $?
}

That can be useful to give specific and use friendly errors and advice, 
but it starts to get tedious to write pretty fast if you do it for 
everything.  'set -e' is much faster, but more user hostile.


> I'd like to know when the script is copying files, and when it is erasing files.
> 
> I could add echo statements, but it would be much simpler if the actual bash 
> commands simply echoed to the screen.

I usually add echo's since you can be more use friendly, as above.


> Is there a simple way to do this?

Yup.  First, many commands have a verbose mode, like 'cp -v' that tell 
you what they are doing.  That might be enough.  See the man pages for 
external commands and the bash 'help' command for internal ones like cd.

Second, Matt already mentioned 'set -x' which is intended for debugging. 
  You might also look at the PS4 prompt, which is the debugging prompt. 
  Note that the first character will be repeated to denote the shell 
depth (in case of sub-shells), so something like this might work:
	PS4='+running:'

There is also 'set -v' for verbose mode.  In theory that is what you 
want, but in practice I usually use -x as Matt suggested because I 
usually find it more useful.  Note 'set +x' or 'set +v' will turn them 
back off, so you can have feedback for only part of the script.

Or you can go nuts and use verbose, set -x and set -v...  Play with it 
and see what you like.

Finally, you don't need to use the 'set' command if you want settings 
for the *entire* script.  You can do it in the shebang line, like:
	#!/bin/bash -x

HTH,
JP
----------------------------|:::======|-------------------------------
JP Vossen, CISSP            |:::======|      http://bashcookbook.com/
My Account, My Opinions     |=========|      http://www.jpsdomain.org/
----------------------------|=========|-------------------------------
"Microsoft Tax" = the additional hardware & yearly fees for the add-on
software required to protect Windows from its own poorly designed and
implemented self, while the overhead incidentally flattens Moore's Law.
___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug