Bash Tips and Pitfalls: Difference between revisions
Jump to navigation
Jump to search
(→Miscellaneous: Different ways to launch process in the background...) |
(Re-organized, each tip has its own title now) |
||
Line 58: | Line 58: | ||
</source></div> |
</source></div> |
||
=== Empty a file keeping permissions === |
|||
=== Miscellaneous === |
|||
Empty a file named <tt>filename</tt>, keeping the same permission and user/group: |
Empty a file named <tt>filename</tt>, keeping the same permission and user/group: |
||
Line 65: | Line 65: | ||
</source> |
</source> |
||
=== Print multi-lines with echo === |
|||
Print multi-lines text with '''echo''': |
Print multi-lines text with '''echo''': |
||
Line 73: | Line 74: | ||
</source> |
</source> |
||
=== Get file size === |
|||
The different ways to extract file size in a Bash script: |
The different ways to extract file size in a Bash script: |
||
Line 83: | Line 85: | ||
</source> |
</source> |
||
=== Read file content into env variable === |
|||
Read the content of a file into an environment variable: |
Read the content of a file into an environment variable: |
||
<source lang="bash"> |
<source lang="bash"> |
||
Line 89: | Line 92: | ||
</source> |
</source> |
||
=== Get the PID of a new process === |
|||
Getting the ''pid'' of a new process (when other processes with same name are already running) |
Getting the ''pid'' of a new process (when other processes with same name are already running) |
||
<source lang="bash"> |
<source lang="bash"> |
||
Line 99: | Line 103: | ||
</source> |
</source> |
||
=== Get the PID of a running process === |
|||
Getting the ''pid'' of a running process |
Getting the ''pid'' of a running process |
||
<source lang="bash"> |
<source lang="bash"> |
||
Line 104: | Line 109: | ||
</source> |
</source> |
||
=== Launch a process in the background === |
|||
Different ways to launch process in the background (unordered - might be useful one day...). The double ampersand trick comes from [http://www.linuxquestions.org/questions/linux-newbie-8/can-bash-create-a-detached-process-340634/ here]. |
Different ways to launch process in the background (unordered - might be useful one day...). The double ampersand trick comes from [http://www.linuxquestions.org/questions/linux-newbie-8/can-bash-create-a-detached-process-340634/ here]. |
||
<source lang="bash"> |
<source lang="bash"> |
Revision as of 08:43, 6 November 2009
Tips
Parsing Command-Line Option Parameters
- To ease parsing, pre-parse with executable getopt (see here for more information and examples).
#!/bin/bash
# (old version)
args=`getopt abc: $*`
if test $? != 0
then
echo 'Usage: -a -b -c file'
exit 1
fi
set -- $args
for i
do
case "$i" in
-c) shift;echo "flag c set to $1";shift;;
-a) shift;echo "flag a set";;
-b) shift;echo "flag b set";;
esac
done
$ ./g -abc "foo"
flag a set
flag b set
flag c set to foo
- Better yet, parse using Bash/sh built-in getopts (see here for more information and examples).
#!/bin/bash
while getopts "abc:" flag
do
echo "$flag" $OPTIND $OPTARG
done
$ ./g -abc "foo"
a 1
b 1
c 3 foo
- To parse option like --value=name ([1])
until [[ ! "$*" ]]; do
if [[ ${1:0:2} = '--' ]]; then
PAIR=${1:2}
PARAMETER=$(echo ${PAIR%=*} | tr [:lower:]- [:upper:]_)
eval P_$PARAMETER=${PAIR##*=}
fi
shift
done
Empty a file keeping permissions
Empty a file named filename, keeping the same permission and user/group:
>filename
Print multi-lines with echo
Print multi-lines text with echo:
$ echo -e "Some text\n...on 2 lines..." # Enable interpretation of backslash escapes (must be quoted!)
Some text
...on 2 lines...
Get file size
The different ways to extract file size in a Bash script:
SIZE=$(stat -c%s "$FILENAME") # Using stat
SIZE=$(ls -l $FILENAME | awk -F" "'{ print $5 }') # Using ls / awk
SIZE=$(du -b $FILENAME | sed 's/\([0-9]*\)\(.*\)/\1/') # Using du
SIZE=$(cat $FILENAME | wc -c) # Using cat / wc
SIZE=$(ls -l $FILENAME | cut -d " " -f 6) # Using ls / cut
Read file content into env variable
Read the content of a file into an environment variable:
PID=`cat $PIDFILE`
read PID < $PIDFILE
Get the PID of a new process
Getting the pid of a new process (when other processes with same name are already running)
oldPID=`pidofproc /usr/bin/ssh`
/usr/bin/ssh -f -N -n -q -D 1080 noekeon
RETVAL=$?
newPID=`pidofproc /usr/bin/ssh`
uniqPID=`echo $oldPID $newPID|sed -e 's/ /\n/g'|sort|uniq -u`
echo $uniqPID
Get the PID of a running process
Getting the pid of a running process
pid=$(pidof -o $$ -o $PPID - o %PPID -x /bin/ssh)
Launch a process in the background
Different ways to launch process in the background (unordered - might be useful one day...). The double ampersand trick comes from here.
myprocess.exe &
exec myprocess.exe
exec myprocess.exe &
( ( exec myprocess.exe & ) & )
nohup myprocess.exe &
( ( nohup myprocess.exe & ) & )
Pits
A list of frequent gotcha's !
Description | Example |
---|---|
Space! - Don't forget to add spaces whenever necessary, in particular around brace in function definition, or in test conditions for ifs. |
if -space- [ -space- -f /etc/foo -space- ]; then ... |
Quote - Always quote parameters, variables passed to test in if ... then ... else: |
if [ "$name" -eq 5 ]; then ... |
For loops with file - Use simply * to list files in for loops, not `ls *`: |
for file in *; cat "$file"; done # SUCCEEDS, even if white space
for file in `ls *`; cat "$file"; done # FAILS miserably
|
Space variable setting - There must be no space between the variable name and the subsequent equal sign. Also the variable name must not be prefixed with a $ |
srcDir = $1 # WRONG - spaces around = sign
$srcDir=$1 # WRONG - variable name must not have $ prefix
srcDir=$1 # CORRECT
srcDir="$1" # BEST
|
Semi-colon in find - Semi-colon in find commands must be escaped ! |
find . -exec echo {} ; # WRONG - semi-colon not escaped
find . -exec echo {} \; # CORRECT
|
Variable not exported outside parens |
( read pid < $PID_FILE ) 2> /dev/null # WRONG - var pid not kept
read pid 2> /dev/null < $PID_FILE # CORRECT
|
Wrong redirection order |
read pid < $PID_FILE 2> /dev/null # WRONG - error msg if $PID_FILE
# doesn't exist
read pid 2> /dev/null < $PID_FILE # CORRECT
|
Using a bash built-in instead of external program Bash built-in commands override external commands with same name (eg. kill and echo) |
$ type kill # kill is a shell builtin
$ type /bin/kill # /bin/kill is /bin/kill
$ /bin/kill -v # kill (cygwin) 1.14
|