Solved

Issues in Unix bash shell script

Posted on 2013-01-31
18
680 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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

FreeBSD on EC2 FreeBSD (https://www.freebsd.org) is a robust Unix-like operating system that has been around for many years. FreeBSD is available on Amazon EC2 through Amazon Machine Images (AMIs) provided by FreeBSD developer and security office…
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…
Learn the basics of modules and packages in Python. Every Python file is a module, ending in the suffix: .py: Modules are a collection of functions and variables.: Packages are a collection of modules.: Module functions and variables are accessed us…
Learn how to get help with Linux/Unix bash shell commands. Use help to read help documents for built in bash shell commands.: Use man to interface with the online reference manuals for shell commands.: Use man to search man pages for unknown command…

708 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

18 Experts available now in Live!

Get 1:1 Help Now