Register
It is currently Wed Oct 22, 2014 8:21 pm

Request for fine-tuning


All times are UTC - 6 hours


Post new topic Reply to topic  [ 6 posts ] 
Author Message
 PostPosted: Fri Feb 20, 2009 5:22 pm   

Joined: Fri Feb 20, 2009 4:33 pm
Posts: 4
Location: WNY State
Hi, folks.
I've done very little Bash scripting, and I'm trying to overcome my lazy past! I'd appreciate very much if you all would try out and analyze this script for me. It seems to work just fine. But I am not particularly pleased: while it does what it needs to do, it is not very elegant nor is it "tight."

Back in the day, I dabbled in some small programs in Basic, Pascal and C, and I'm just not getting the same feel of satisfaction with this script. OK, I realize this is not the same as a programming language -- even Basic-- but I get the feeling it's my ineptitude rather than the limitations of Bash scripting that is the issue here.

SCRIPT PURPOSE:
To generate subdirectories for mountpoints, based on user input.
BACKGROUND:
A number of the "fun" distros like Arch and some of the Slackware-derived distros have a terrible interface for adding mountpoints for additional data partitions at install time.
I'm a distro junkie: I have 2 HDDs with slots for 15 distros, and a total of 5 HDDs with (maybe) 60 partitions total. Some are root for a distro, some are data partitions I want accessible no matter what OS I'm booted into. Some months ago I wrote a different script that takes every "sdxnn" entry in the /dev directory and creates a corresponding directory in /mnt for a mountpoint.
Easy. But I want more!
THIS ONE:
I've long been peeved by the fact that partition sda1 is followed by sda11, sda12, etc. -- and then sda2, sda3, etc. come after sda15. The obvious solution for such a nit-picker is to make mountpoints that use double-digit numbering:
/mnt/sda01
/mnt/sda02 ...
/mnt/sda10
/mnt/sda11
/mnt/sda12

This script does that. But it's based on user input, rather than automatically polling the contents of /dev.
I've tried to trap the most obvious user errors, like entering the wrong letter for a drive or exceeding 15 partitions per drive --per the newer Linux kernel desire to make the whole world consist solely of serial/scsi drives. A bit of whimsy in the error output. . . forgive me. I am easily amused.

I rely pretty heavily on "case", with a few "if/then/elif/then" controls.
Does anyone see any obvious faults? Can anyone suggest a way to tighten up the algorithm?


Code:
#1 /bin/bash
# sbl-mountpoints2.sh
# creates mountpoints for HDD partitions based on user input.
# copyright SilverBear 2009 under GPL
# This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
# Contact: silverbear at sblinux dot org
# ##############################################################################################
clear # Clear the screen.
directory=${1-`pwd`}
echo "********************************************************************************************"
echo "                    You are now working in $directory"
echo "********************************************************************************************"
echo "Be CERTAIN this is the correct directory before you proceed! "
echo "HDD partition mountpoints will be created inside this directory."
echo "It should most likely be /mnt --so that you wind up with /mnt/sda01, /mnt/sda02, and so forth."
echo " "
# #################################
#  Timeout_read for number input
TIMELIMIT=30         # 30 seconds
# #################################
# CHOOSING THE HARD DISK DRIVE
echo "This script will create mountpoints under /mnt for your additional data partitions."
echo "Choose a letter to create mountpoints for partitions on that drive. ** lOWER cASE, PLEASE!  :-) **"
echo "sd[a]"
echo "sd[b]"
echo "sd[c]"
echo "sd[d]"
echo "sd[e]"
echo "sd[f]"
echo "sd[g]"
echo "sd[h]"
echo "-- or type [q] to quit"
echo "********************************************************************************************"
echo "You have about another 20 seconds to choose your HDD by letter.  Hit ENTER key when finished"
echo "Hit the key combination *control-z* at any time to abort this script."
echo "********************************************************************************************"
echo " "
# get keyboard input
read -t $TIMELIMIT hdd <&1
#                      ^^^
#  In this instance, "<&1" is needed for Bash 1.x and 2.x,
#  but unnecessary for Bash 3.x and presumably Bash 4.x as well.
echo
   if [ -z "$hdd" ]  # Is null?
   then
  echo "Timed out, variable still unset."
  exit 1
   elif [[ "$hdd" != [a-h] ]] 
   then
  echo "-------------------------------------------"
  echo "You didn't choose a HDD between sda and sdh"
  echo "-------------------------------------------"
  echo "Script termination: user passed a bad variable."
  echo "---------------------------------------------------------------------------------------------------"
  echo "You know, many computer malfunctions occur in the interface between the chair and the keyboard."
  echo " . . . loser."
  echo
  echo "Sorry. . . Just joking."
  echo "I really admire you.  I tend to mask my true feelings with insults. Why do you think that is?"
  echo
  echo
  exit 1
   else 
  echo "Making mountpoints for HDD  $hdd"
   fi 
echo
#
case "$hdd" in
("a")
echo "We are making mountpoints for partitions on disk sda --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("b" )
echo "We are making mountpoints for partitions on disk sdb --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("c" )
echo "We are making mountpoints for partitions on disk sdc --right? ((y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("d" )
echo "We are making mountpoints for partitions on disk sdd --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("e" )
echo "We are making mountpoints for partitions on disk sde --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("f" )
echo "We are making mountpoints for partitions on disk sdf --right? ((y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("g" )
echo "We are making mountpoints for partitions on disk sdg --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("h" )
echo "We are making mountpoints for partitions on disk sdh --right? (y/n --lower case)"
read ok
if [[ $ok == "n" ]]
then echo "Something is wrong, then."
echo "I quit.  Restart the script and try it again."
echo " "
exit 1
else echo "OK! lets's continue. . ."
fi
;;
("q")
echo "You chose to quit this script."
echo "Goodbye."
exit 0
esac
# ##################################################################################
# set number of partition mountpoints for a hard disk drive
echo
echo -n "How many partitions on disk sd${hdd}? ( type a number from 1 to 15)"
read -t $TIMELIMIT partitionz <&1
#                            ^^^
#  In this instance, "<&1" is needed for Bash 1.x and 2.x,
#  but unnecessary for Bash 3.x and presumably Bash 4.x as well.
echo
   if [ -z "$partitionz" ]  # Is null?
   then
  echo "Timed out, variable still unset."
  exit 1
   elif [ "$partitionz"  -gt "15" ]
   then
  echo "---------------------------------------------------------------------------------------------------"
  echo "Linux kernels above 2.6.20 only address 15 or fewer partitions per HDD. Start the script again."
  echo "---------------------------------------------------------------------------------------------------"
  echo "Script termination: user passed a bad variable."
  echo "---------------------------------------------------------------------------------------------------"
  echo "You know, many computer malfunctions occur in the interface between the chair and the keyboard."
  echo " . . . loser."
  echo
  echo "Sorry. . . Just joking."
  echo "I really admire you.  I tend to mask my true feelings with insults. Why do you think that is?"
  echo
  echo 
  exit 1   
   else 
  echo "Number of partitions chosen = $partitionz"
   fi 
# set number of subdirectories for partitions
case "$partitionz" in
(1)
echo "You have 1 partition on sda."
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
;;
(2)
echo "You have 2 partitions on sda."
for i in  {1,2} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(3)
echo "You have 3 partitions on sda."
# make directories with initial zero in name
for i in  {1..3} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(4)
echo "You have 4 partitions on sda."
# make  directories with initial zero in name
for i in  {1..4} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(5)
echo "You have 5 partitions on sda."
# make  directories with initial zero in name
for i in  {1,2,3,5} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(6)
echo "You have 6 partitions on sda."
# make  directories with initial zero in name
for i in  {1,2,3,5,6} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(7)
echo "You have 7 partitions on sda."
# make  directories with initial zero in name
for i in  {1,2,3,5,6,7} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(8)
echo "You have 8 partitions on sda."
# make  directories with initial zero in name
for i in  {1,2,3,5,6,7,8} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(9)
echo "You have 9 partitions on sda."
# make  directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits..."
mkdir  sd${hdd}0$i
done
;;
(10)
echo "You have 10 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
(11)
echo "You have 11 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10,11} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
(12)
echo "You have 12 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10..12} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
(13)
echo "You have 13 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10..13} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
(14)
echo "You have 14 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10..14} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
(15)
echo "You have 15 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
for i in  {10..15} ; do
echo "making double digit partitions..."
mkdir  sd${hdd}$i
done
;;
esac
# ##################################
#  End of script message
echo; echo "   -- Done."
#  #################################
echo "$partitionz mountpoints created in /mnt for sd$hdd partitions."
echo " Here you go:"
ls -l
# ##################################
#  End of script message
echo
echo; echo "          To add partition mountpoints for another HDD, run the script again."
echo       "          ___________________________________________________________________"
echo       "          Tip: When you hit the up-arrow key, you reload the last entered bash command."
echo " "
exit 0


thanks,
SilverBear


Last edited by SilverBear on Fri Feb 20, 2009 10:17 pm, edited 1 time in total.

Top
 Profile WWW  
 PostPosted: Fri Feb 20, 2009 6:33 pm   

Joined: Fri Feb 20, 2009 4:33 pm
Posts: 4
Location: WNY State
Woops! I see one problem now.
I chose 10 partitions for my sde drive and got
sde01
sde02
sde03
sde05
sde06
sde07
sde08
sde09
sde{10}

So comment on other problems besides this one, please.

Here is what I substituted for the problem code in "case (10)"
Code:
(10)
echo "You have 10 partitions on sda."
# make directories with initial zero in name
for i in  {1,2,3,5,6,7,8,9} ; do
echo "Changing single digit enumeration to double digits...making double digit partitions..."
mkdir  sd${hdd}0$i
done
# make directories for partitions  -ge 10
echo "making double digit partitions..."
mkdir  sd${hdd}10
;;


Not elegant, but it removes the array consisting of only one element --which apparently was the problem.

--SB


Last edited by SilverBear on Fri Feb 20, 2009 6:40 pm, edited 1 time in total.

Top
 Profile WWW  
 PostPosted: Fri Feb 20, 2009 6:34 pm   

Joined: Mon Nov 17, 2008 7:25 am
Posts: 221
If I did understand you correctly, you wish to mount all your extra partitions in some kind of sorting?

why not just do a for loop?

Code:
#!/bin/bash
mnt=/mnt/disks/
for i in $(ls --color=no /dev/sd*|egrep "[0-9]$"); do
   dev=$(echo $i | sed -e "s/\/dev\/\(.*\)/\1/")
   [ -d $mnt/$dev ] || mkdir $mnt/$dev
   mount $i $mnt/$dev
done


This will automatically mount all your disks and create directories named like the device in the path specified in $mnt while ignoring all devices that doesn't end with a number (thats what the egrep is for :P)

Best regards
Fredrik Eriksson


Top
 Profile  
 PostPosted: Fri Feb 20, 2009 10:16 pm   

Joined: Fri Feb 20, 2009 4:33 pm
Posts: 4
Location: WNY State
Thank you for the quick reply, Fredrik.

That isn't what I'm trying to do. I don't need to mount anything, just create the mountpoints, but according to a different naming method. I also want it according to user input, so it can be done at a time other than when the target OS is running which is the only time /dev is populated for that filesystem.

I already have a different script the creates mountpoints based on the listing in /dev, for use in a running OS.

Code:
#!/bin/sh
#  sbl-mkdir2mnt1.sh
#  mkdir in /mnt for every instance of /dev/sd*nn
#  SilverBear 2008-04-13
#
#
#
#

#  Set shell environment
PATH=/bin:/dev:/mnt:
cd /dev
for file in sd*; do
echo "Adding $file to /mnt directory..."
mkdir /home/silverbear/mnt/$file
done
# get rid of mountpoints for names of entire disks
cd /mnt
rmdir sd?
#get rid of sd?4
rmdir sd?4
echo "****************************************"
echo "Finished creating partition mountpoints."
echo "****************************************"
echo " "
echo "If you don't believe me, here's the directory listing. See for yourself!"
ls -l
exit 0


Like your script, this one gives a mountpoint name like these, which do not sort in correct order in a ls -l list, or in Konqueror.
/mnt/sda1
/mnt/sda10
/mnt/sda11
/mnt/sda12
/mnt/sda2
/mnt/sda3
. . . and so on.

The new script I'm working on puts a zero before the numbers 1-9, so the mountpoint subdirectories lines up in order:
/mnt/sda01
/mnt/sda02
/mnt/sda03
/mnt/sda05
/mnt/sda02
/mnt/sda06
/mnt/sda07
/mnt/sda08
/mnt/sda09
/mnt/sda10
/mnt/sda11
/mnt/sda12


While your for loop was very tight, it gave me some errors while testing it. Sad to say I don't really understand it, though.
For example, I've never heard of a --color=no switch for the ls command. What is the purpose of that in this script?
The sed -e . . . part is also something I'll have to try to figure out.

Thanks -- I have something to study, and perhaps adapt.
:)


Top
 Profile WWW  
 PostPosted: Sat Feb 21, 2009 5:14 am   

Joined: Mon Nov 17, 2008 7:25 am
Posts: 221
Okey, I'll try to explain, I wrote it while being somewhat drunk last night :P

the --color=no switch is just some old relic I use because of some applications use of ansi coloring.
^[31 is a color code which can be interpreted by some applications as just ^[31 and not as a color. I've had errors occuring just because it cant find the file ^[31filename.txt

the sed command just cuts out the device name if there would be a /dev/ before it.
-e just says it's an expression, this is not really needed if you're only doing 1 expression in sed, if you want to do 2 you need to do -e "expression" -e "next expression"

The user input you wish to get is "a" and "c" and then generate sdaX to sdcX or did i missunderstand again?
I'll write a new one and explain it :)

Code:
#!/bin/bash
#!/bin/bash
mnt="/mnt"

# This function is just to create the alphabet list between the first user input to the second.
# The tricky thing with this is the case statement. It checks for characters that's in the range between ex. [a-c] and ignores the rest
function create_list {
   for i in {a..z}; do
      case $i in
         # Magic part :D
         [${1}-${2}])
            # Fill a variable with the correct alphabetic characters :)
            list="$list $i"
         ;;
      esac
   done
}

# Read input and print a question
read -p "From? " from
read -p "To? " to

# Execute the above script with the parameters given from our reads
create_list $from $to

# Loop throu the list of characters that's in the range of $form and $to (a to e for example)
for a in $list; do
   # Nested for loop to look for the devices.
   for i in $(ls /dev/sd${a}*); do
      # We need to reformat the string that "ls" has given us so we can work with it.
      dev=$(echo $i | cut -d'/' -f2)
      # And to figure out if this is a number below 10 we chop that out aswell :)
      # the 4,5,6,7 is telling cut that we want the 4th, 5th, 6th an 7th byte of the string,
      # doubt you'll have more then a-z drives with more partitions then 9999.
      num=$(echo $dev | cut -b4,5,6,7)
      # if statement to check if the number is lesser then 10
      if [ $num -lt 10 ]; then
         num="0$num"
         # Reconstruct the device name with the added 0 before the number lesser then 10
         # the regular expression says "the first 3 characters are alphanumeric" which will match sdX, this
         # is saved to a buffer for later use by invoking \(expression\).
         dev=$(echo $dev | sed "s/^\(\w\{3\}\).*$/\1$num/")
      fi
      # Create $mnt/$dev if $mnt/$dev does not exist, and do it recursivly
      [ -d $mnt/$dev ] || mkdir -p $mnt/$dev
   done
done


This should work properly, i even tested it as far as i could. Let me know if you run into any problems.
Also I hope my comments aren't to tricky :P

Best regards
Fredrik Eriksson


Top
 Profile  
 PostPosted: Sat Feb 21, 2009 9:21 am   

Joined: Fri Feb 20, 2009 4:33 pm
Posts: 4
Location: WNY State
Very clear and easy for me to understand.

I don't think I'll have time today to play with it, but I look forward to trying it out tomorrow.
Thanks again, Fredrik! I appreciate your taking the time to go into detail for me.

--SilverBear


Top
 Profile WWW  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP