Solved

Issues in Unix bash shell script

Posted on 2013-01-31
18
694 Views
Last Modified: 2013-02-08
Hi, in the below Unix bash shell script I am trying to solve 3 different issues that I am facing:

Note:
$LOGNAME - a unique user name on Unix server.
/directory1/tmp - a directory where all these processes will occur.

for dir in $(find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*")
do
   echo "Remove $dir (y/n)?  "; read YN
   [[ $YN = Y || $YN = y ]] && rm -r $dir 
done

Open in new window


1). How to disable not necessary exception messages for other user's directories?  Directories can be searched and shown only for that particular user who is currently operating in the Unix environment and not for any other users directories.
For example: if someone other Unix user have created a directory that directory shows up as following in the prompt.  
find: cannot read dir /directory1/tmp/direcory12: Permission denied

Open in new window

I just don't want to see this prompt message, because it is not my directory and I don't have permissions to delete it anyway.

2). Currently 'Y' or 'y' are standing for Yes and any other letters, number, or characters are standing for No. How may I narrow these down to just 'y' and 'n' if that is possible?

3). How may I delete SAS* directories without prompt asking me if I would like to delete sub-directories in that SAS* directory?  When a SAS* directory is deleted then all its sub-directories should be deleted as well automatically.

Example of prompt at the login:
find: cannot read dir /directory1/tmp/directory12: Permission denied
Remove /directory1/tmp/SASdir1 (y/n)?  
n
Remove /directory1/tmp/SASdir2 (y/n)?  
y
Remove /directory1/tmp/SASdir2/SASsubdir1 (y/n)?  
n
Remove /directory1/tmp/SASdir2/SASsubdir2 (y/n)? 
n

Open in new window


Any suggestions or comments will be greatly appreciated!
Thank you!
0
Comment
Question by:labradorchik
  • 6
  • 5
  • 4
  • +2
18 Comments
 
LVL 47

Assisted Solution

by:dlethe
dlethe earned 150 total points
ID: 38841234
1) add 2>/dev/null to the find line this will put errors in bit bucket
2) Learn the case statement  (this is overkill but good form as it shows you how to keep them in loop or exit.

while getopts $OPTIONLIST Option
do
  case $Option in
    q     ) echo "all done";exit;;
    h     ) usage;exit;;
    y     ) dotheYESfunction;;
    Y     ) dotheYESfunction;;
    *     ) echo "Unimplemented option chosen. Choosing NO.";exit 1;;   # DEFAULT
  esac
# this can be used to give them help or you could then change doTheYESfunction to CRUNCH=1 and then test for the value and do the logic here
done

#3  rm -f {list of whatever} suppresses the are-you-sure.
rm -rf {list}  deletes all files and subdirectories, so make darn sure you test the script first.
0
 
LVL 40

Expert Comment

by:omarfarid
ID: 38841244
try this

for dir in $(find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null)
do
   echo "Remove $dir (y/n)?  "; read YN
   case $YN in
   Y|y)
       rm -r -y $dir
       ;;
   N|n)
       echo "$dir not removed"
       ;;
   *)
       echo bad option
       ;;
   esac
done
0
 
LVL 47

Expert Comment

by:dlethe
ID: 38841318
For what it is worth the script still has some holes,
you need to be aware that directory names can have spaces and special characters in it.  

if there is a directory with an embedded space like "Evil boot usr" and you run this from / then your script will happily blow away /usr and /boot and you'll never know until it is too late

(Or any user could create a directory with just / in the path (specifically " /"  and then you will blow the entire computer away no matter what directory you run the script from .. if you are root)

But probably more than you wanted to know, just saying that when learning scripting one has to be aware of such things.
0
 

Author Comment

by:labradorchik
ID: 38841343
Thank you very much for your comments!!

So both below scripts will delete all directories and their sub-directories without another prompt for sub-directories, correct?  
rm -rf $dir
and
rm -r -y $dir
0
 
LVL 40

Expert Comment

by:omarfarid
ID: 38841381
the -y should be -f (typo from my side)
0
 
LVL 10

Expert Comment

by:ddiazp
ID: 38841472
Nvm..
0
 

Author Comment

by:labradorchik
ID: 38841650
I just tested below script with 3 directories (SASdir1, SASdir2, SASdir3). SASdir1 has two sub-directories (SASsubdir1a, SASsubdir1b), SASdir2 has one sub-directory (SASsubdir2a),  and SASdir3 does not have any sub-directories.:
for dir in $(find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null)
do
   echo "Remove $dir (y/n)?  "; read YN
   case $YN in
   Y|y)
       rm -rf $dir
       ;;
   N|n)
       echo "$dir not removed"
       ;;
   *)
       echo bad option
       ;;
   esac
done 

Open in new window


Below are the prompts:  

Remove /directory1/tmp/SASdir1 (y/n)?  
n
/directory1/tmp/SASdir1 not removed
Remove /directory1/tmp/SASdir1/SASsubdir1a (y/n)?  
n
/directory1/tmp/SASdir1/SASsubdir1a not removed
Remove /directory1/tmp/SASdir1/SASsubdir1b (y/n)?  
n
/directory1/tmp/SASdir1/SASsubdir1b not removed
Remove /directory1/tmp/SASdir2 (y/n)?  
n
/directory1/tmp/SASdir2 not removed
Remove /directory1/tmp/SASdir2/SASsubdir2a (y/n)?  
r
bad option
Remove /directory1/tmp/SASdir3 (y/n)?  
N
/directory1/tmp/SASdir3 not removed
 

Open in new window


Question: How may I bypass sub-directories prompts? I just need delete directories with all sub-directories already included in the process.

For example: if the answer for SASdir1 is y/n, then prompt should ask to delete the next directory which is SASdir2.

Note: the reason for this process is that every unneeded directory has more than 20 sub-directories. If a particular SAS* directory is not needed then its sub-directories will be not needed as well.
0
 
LVL 48

Expert Comment

by:Tintin
ID: 38841947
No need for a script, you can do it with a single find command, ie:

find /directory1/tmp -maxdepth 1 -type d -a -user $LOGNAME -a  -name "SAS*" -ok rm -fr {} \; 2>/dev/null

Open in new window

0
 

Author Comment

by:labradorchik
ID: 38851193
Hi Tintin,
Please check your command, because when I run your command I don't even get any messages from the prompt. May be something is missing in this command?

Note: currently I am just running your single command and that's it.

Tintin, can you may be suggest how the original above script can be modified so that sub-directories would not show up in the prompt messages?
Thank you!
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

Author Comment

by:labradorchik
ID: 38852446
Anyone else would like to comment on the above script?
0
 
LVL 40

Expert Comment

by:omarfarid
ID: 38852513
what is left unanswered ?
0
 
LVL 47

Expert Comment

by:dlethe
ID: 38852555
The script above won't give you any output. It will just delete the single-level directories beginning with "SAS".  

Prove it by changing "rm -fr" to "ls -l"  so it doesn't blow stuff away and just does ls -l on the files it would ordinarily remove, and change "SAS*" to something less restrictive so you know it is actually finding things
0
 

Author Comment

by:labradorchik
ID: 38852580
Unfortunately, Tintin's script does not work. I am not getting any output and all directories are still there, so nothing was deleted.

Script below works, but I am still getting messages asking to delete sub-directories and I don't want that:

for dir in $(find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null)
do
   echo "Remove $dir (y/n)?  "; read YN
   case $YN in
   Y|y)
       rm -rf $dir
       ;;
   N|n)
       echo "$dir not removed"
       ;;
   *)
       echo bad option
       ;;
   esac
done 

Open in new window


I just want to delete directories with all sub-directories together at once. How can this be done?
0
 
LVL 40

Assisted Solution

by:omarfarid
omarfarid earned 150 total points
ID: 38852637
you can run find first and redirect output to file then sort the file and then remove dirs from that file:

find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null > SASdirs
sort SASdirs > mydir
for dir in `cat mydir`
do
   if [ -d $dir ]
   then
     echo "Remove $dir (y/n)?  "; read YN
     case $YN in
     Y|y)
         rm -rf $dir
         ;;
     N|n)
         echo "$dir not removed"
         ;;
     *)
         echo bad option
         ;;
     esac
   fi
done
0
 
LVL 40

Expert Comment

by:omarfarid
ID: 38852649
I don't have a system to test my script, but if you find it is not working as required, then

try to replace sort by sort -r

or

you can post the output of sort command (mydir file)
0
 
LVL 48

Accepted Solution

by:
Tintin earned 200 total points
ID: 38854582
If my onliner didn't work, it must be to do with your version of find.

Change

for dir in $(find /directory1/tmp -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null)

to

for dir in $(find /directory1/tmp -maxdepth 1 -type d -a -user $LOGNAME -a  -name "SAS*" 2> /dev/null)
0
 
LVL 47

Expert Comment

by:dlethe
ID: 38854646
... or, do a "man find" to make sure the syntax is correct, and make the necessary changes.

When you use UNIX as long as some of us, we (well at least I) sometimes forget to clarify that we crank these out off top of our heads and we don't bother to remember the variations between linux, solaris, aix, and so on.

In fact, your choice of whether you use ksh, bash, sh, or csh as your shell and what username you log in to can cause scripts to easily break.

So your lesson for today is to:

1.  add
#!/bin/sh  (or whatever shell you know will work) to first line of the script. This makes it consistent and will prevent the code from breaking depending on what shell you are using

2. add
PATH=/usr/bin;/sbin;  # add full paths for whatever directory all the executables are that you call, that way your program will find them.  This is the 2nd line of the script
0
 

Author Closing Comment

by:labradorchik
ID: 38869845
Tintin, your one liner worked fine after I defined everything in in my .login file and then did some testing. Thank you!
Thank you everyone for all your examples, comments and suggestions!!
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Oracle Finace 3 67
Image not there 4 45
How do disable only TLSv1.0 in Oracle Sun One 7.1 Server 9 74
Solaris 4.1.3 cloning and booting 13 72
Background Still having to process all these year-end "csv" files received from all these sources (including Government entities), sometimes we have the need to examine the contents due to data error, etc... As a "Unix" shop, our only readily …
Why Shell Scripting? Shell scripting is a powerful method of accessing UNIX systems and it is very flexible. Shell scripts are required when we want to execute a sequence of commands in Unix flavored operating systems. “Shell” is the command line i…
The viewer will learn how to dynamically set the form action using jQuery.
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now