Techniques of writing scripts in Bash - Advanced 11-17-2012, 03:35 AM
#1
Just published this on my personal blog > http://net-solutions.pro and i would like to share it with you as wel. Also any suggestions are welcomed (i am very interested into
this)
library file functions in this example can be downloaded HERE
test file HERE
Here's how you can speed up the work, as well as improve the reliability of scripts.
Tip 1
In the beginning of each script we'll put something like:
The echo command, by the way, is necessary here because when you click <y> you will not have a line feed, therefore, next string will go to any output .
Tip 2
This is the key advice. In order to not write every time the same thing - use libraries function .
Get a library , (myfunc.sh - as example) and place it, such as / usr / bin. When writing the script, it will help to reduce your work.
Here's an example
You can write also another similar function myAskYNE, in which the return is replaced by exit. Then the record will be even easier:
Advantages are obvious: a) write less code, and b) the code easier to read, and c) are not distracted by little things like boxes "(y / [a]):" the test (note that [a] means any, and climbed into the square quotes indicate that this is the default).
Finally here. In order to use the functions from the library, it should not forget to include it in the script:
Note that the name is assigned to the script. This allows you to specify the name of the script once, and therefore, you can duplicate the line and replace the name of the library to connect the other library functions, if necessary.
Now, any script that starts with these three lines never do something without asking.
Tip 3
Will develop and demonstrate the success of a few obvious features with minimal commentary.
It will turn your attention to the combination 1> & 2 after the echo. The fact is that your script will probably display some valuable information. Combination 1> & 2 is redirecting output to standard error. And when you call the script as follows:
My -script.sh> out.txt
My -script.sh | less
there will be no unnecessary errors and service messages, only what you really want to print.
Tip 4
In Bash is not very good things with the return of a value from the function. However, with its own library that question is easily solved. Just please create a variable in which the function will write the value, and to get out of the function that analyze this variable. By the way, variables are at the beginning of the library of your functions. Also, you can have other variables, which you can use everywhere. Here is the beginning of your library functions:
curPath = # variable with the current absolute path where the script
CRES = # variable to return the text values of the functions
pYes = # option - yes, which is discussed later
Now we can add to the collection a useful function:
Here is an example of its use:
cat << 'EOF'
Make your choice:
------------------------
a) Step 1
b) Action 2
.) Output
EOF
input1 "Your choice:" "AB."
echo "The choice was: $ CRES "
This feature limits the keystrokes to a list of (in this case a, b, and point). No other keys will not be seen. The example also shows the use of a variable return ($ cRes). It returns the letter, pressed by the user.
Tip 5
What script with no parameters? Their processing written tons of literature. Share your vision.
1.Ideally, the parameters are treated regardless of their sequence.
2.I do not like using the single-letter options (and therefore getopts) because is kinda confusing. For a script -r means replace, for the other replicate, and for the third remove. Looks impossible. So I use the two notations, and at the same time: a)-show-files-only, b)-sfo (as a reduction from the previous).
3.The script should generate an error of unknown key. This to help identify errors in writing parameters.
4. We start from the board rule: never run the script without confirmation. But add to this the important exception - if no key-yes (key, of course, may be used).
5. Keys can be accompanied by value. In this case, the long options is generally valid:-source-file = my.txt , or -sf my.txt
In light of this treatment options might be:
This code provides the following features:
. / Test.sh-sf mysource-df mydest
. / Test.sh - Source-file = MySource - dest-file = mydest
. / test.sh - Source-file = MySource - dest-file = mydest - Yes
-Parameters can be specified in any order and combination of full and reduced form of keys.
-Because the parameters are required, a test verify their presence >> checkParm.
-If no key-yes, there will always prompt for confirmation.
This is a basic piece that can be further developed. For example, add a couple of functions processing parameters in our library:
The cycle of processing parameters will look much more better:
In fact, this cycle can be copied from the script to the script without thinking about anything, except the names of keys and a variable name for this key. And in this case, they are not repeated, and the opportunity for error.
no limit to perfection, and can be a long time "improve" functions, such as procParmS check for non-null value, and the third parameter to fall out in error in this case. And so on.
library file functions in this example can be downloaded HERE
test file HERE
Hope you'll enjoy it.
this)
library file functions in this example can be downloaded HERE
test file HERE
Here's how you can speed up the work, as well as improve the reliability of scripts.
Tip 1
In the beginning of each script we'll put something like:
Code:
read-n 1 -P "Are you sure you want to run it (y / [a]):" AMSURE
[ " $ AMSURE " = "y" ] | |
echo "" 1 > & 2Tip 2
This is the key advice. In order to not write every time the same thing - use libraries function .
Get a library , (myfunc.sh - as example) and place it, such as / usr / bin. When writing the script, it will help to reduce your work.
Here's an example
Code:
myAskYN ()
{
local AMSURE
if [-n " $ 1 " ] ; then
Read-n 1 -P " $ 1 (y / [a]): " AMSURE
else
Read-n 1 AMSURE
Fi
echo "" 1 > & 2
if [ " $ AMSURE " = " y " ] ; then
return 0
else
return 1
Fi
}You can write also another similar function myAskYNE, in which the return is replaced by exit. Then the record will be even easier:
Code:
myAskYN "Are you sure you want to run it?" | | exitAdvantages are obvious: a) write less code, and b) the code easier to read, and c) are not distracted by little things like boxes "(y / [a]):" the test (note that [a] means any, and climbed into the square quotes indicate that this is the default).
Finally here. In order to use the functions from the library, it should not forget to include it in the script:
Code:
myAskYN ()
{
local AMSURE
if [-n " $ 1 " ] ; then
Read-n 1 -P " $ 1 (y / [a]): " AMSURE
else
Read-n 1 AMSURE
Fi
echo "" 1 > & 2
if [ " $ AMSURE " = " y " ] ; then
return 0
else
return 1
Fi
}Note that the name is assigned to the script. This allows you to specify the name of the script once, and therefore, you can duplicate the line and replace the name of the library to connect the other library functions, if necessary.
Now, any script that starts with these three lines never do something without asking.
Tip 3
Will develop and demonstrate the success of a few obvious features with minimal commentary.
Code:
sayWait ()
{
local AMSURE
[-N " $ 1 " ] && echo "$ @" 1 > & 2
read-n 1 -P "(press any key to continue)" AMSURE
echo "" 1 > & 2
}
cdAndCheck ()
{
cd " $ 1 "
if ! [ "$ (pwd)" = " $ 1 " ] ; then
echo "!! I can not get to the directory $ 1 - can not continue. leave. " 1 > & 2
exit 1
fi
}
checkDir ()
{
if ! [-D " $ 1 " ] ; then
if [-z " $ 2 " ] ; then
echo "!! No directory $ 1 - can not continue. leave. " 1 > & 2
else
echo " $ 2 " 1 > & 2
Fi
exit 1
fi
}
checkFile ()
{
if ! [-F " $ 1 " ] ; then
if [-z " $ 2 " ] ; then
echo "!! No file $ 1 - can not continue. leave. " 1 > & 2
else
echo " $ 2 " 1 > & 2
Fi
exit 1
fi
}
checkParm ()
{
if [-z " $ 1 " ] ; then
echo "!! $ 2 . Unable to continue. leave. " 1 > & 2
exit 1
Fi
}It will turn your attention to the combination 1> & 2 after the echo. The fact is that your script will probably display some valuable information. Combination 1> & 2 is redirecting output to standard error. And when you call the script as follows:
My -script.sh> out.txt
My -script.sh | less
there will be no unnecessary errors and service messages, only what you really want to print.
Tip 4
In Bash is not very good things with the return of a value from the function. However, with its own library that question is easily solved. Just please create a variable in which the function will write the value, and to get out of the function that analyze this variable. By the way, variables are at the beginning of the library of your functions. Also, you can have other variables, which you can use everywhere. Here is the beginning of your library functions:
curPath = # variable with the current absolute path where the script
CRES = # variable to return the text values of the functions
pYes = # option - yes, which is discussed later
Now we can add to the collection a useful function:
Code:
input1 ()
{
local a1
if [-n " $ 1 " ] ; then
Read-P " $ 1 " -sn 1 CRES
else
Read sn- 1 CRES
Fi
# Check for valid choices
while [ " $ 2 " = " $ {2 # * $ CRES} " ] ; do
Read sn- 1 CRES
Done
echo $ CRES 1 > & 2
}Here is an example of its use:
cat << 'EOF'
Make your choice:
------------------------
a) Step 1
b) Action 2
.) Output
EOF
input1 "Your choice:" "AB."
echo "The choice was: $ CRES "
This feature limits the keystrokes to a list of (in this case a, b, and point). No other keys will not be seen. The example also shows the use of a variable return ($ cRes). It returns the letter, pressed by the user.
Tip 5
What script with no parameters? Their processing written tons of literature. Share your vision.
1.Ideally, the parameters are treated regardless of their sequence.
2.I do not like using the single-letter options (and therefore getopts) because is kinda confusing. For a script -r means replace, for the other replicate, and for the third remove. Looks impossible. So I use the two notations, and at the same time: a)-show-files-only, b)-sfo (as a reduction from the previous).
3.The script should generate an error of unknown key. This to help identify errors in writing parameters.
4. We start from the board rule: never run the script without confirmation. But add to this the important exception - if no key-yes (key, of course, may be used).
5. Keys can be accompanied by value. In this case, the long options is generally valid:-source-file = my.txt , or -sf my.txt
In light of this treatment options might be:
Code:
;
; PDestFile = " $ 1 "
elif [-z " $ 1 " ] ; then Break # Keys ended else echo "Error: unknown key" 1 > & 2 exit 1 fi
shift
done
checkParm " $ pSourceFile " "Do not set the original file"
checkParm " $ pDestFile " "Do not set output file"
if [ " $ pYes " ! = "1" ] ; then
myAskYNE "Are you sure you want to run it?"
Fi
echo "Source = $ pSourceFile , Destination = $ pDestFile "This code provides the following features:
. / Test.sh-sf mysource-df mydest
. / Test.sh - Source-file = MySource - dest-file = mydest
. / test.sh - Source-file = MySource - dest-file = mydest - Yes
-Parameters can be specified in any order and combination of full and reduced form of keys.
-Because the parameters are required, a test verify their presence >> checkParm.
-If no key-yes, there will always prompt for confirmation.
This is a basic piece that can be further developed. For example, add a couple of functions processing parameters in our library:
Code:
procParmS ()
{
[-Z " $ 2 " ] && return 1
if [ " $ 1 " = " $ 2 " ] ; then
CRES = " $ 3 "
return 0
Fi
return 1
}
procParmL ()
{
[-Z " $ 1 " ] && return 1
if [ " $ {# 2} = $ 1 " , = " $ 2 " ] ; then
CRES = " $ {2 # $ 1 =} "
return 0
Fi
return 1
}The cycle of processing parameters will look much more better:
Code:
while [ 1 ] ; do
if [ " $ 1 " = "- Yes" ] ; then
pYes = 1
elif procParmS "-SF" " $ 1 " " $ 2 " ; then
pSourceFile = " $ CRES " ; shift
elif procParmL "- Source-file" " $ 1 " ; then
pSourceFile = " $ CRES "
elif procParmS "DF-" " $ 1 " " $ 2 " ; then
pDestFile = " $ CRES " ; shift
elif procParmL "- dest-file" " $ 1 " ; then
pDestFile = " $ CRES "
elif [-z " $ 1 " ] ; then
Break # Keys ended
else
echo "Error: unknown key" 1 > & 2
exit 1
fi
shift
doneIn fact, this cycle can be copied from the script to the script without thinking about anything, except the names of keys and a variable name for this key. And in this case, they are not repeated, and the opportunity for error.
no limit to perfection, and can be a long time "improve" functions, such as procParmS check for non-null value, and the third parameter to fall out in error in this case. And so on.
library file functions in this example can be downloaded HERE
test file HERE
Hope you'll enjoy it.
![[+]](https://sinister.ly/images/modern/collapse_collapsed.png)