#!/bin/bash echo Hello World tar -cZf /var/my-backup.tgz /home/me/
If you get something like ./hello.sh: Command not found. Probably the first line '#!/bin/bash' is wrong, issue whereis bash or see 'finding bash' to see how sould you write this line.
#!/bin/bash -x
This will produce some intresting output information
PWD=`pwd` # or PWD=$(pwd)
Get absolute path to your script
SELF_PATH=$(cd ${0%/*}; pwd) # imposta il percorso a quello del file corrente e ritorna il percorso corrente __DIR__=$(cd $(dirname "$0"); pwd)
SCRIPT="`readlink -e $0`" SCRIPTPATH="`dirname $SCRIPT`"
summary:
# Redirect stdout to file 1> filename.txt # Redirect and append stdout to file 1>> filename.txt # Redirect stderr to file 2> filename.txt # Redirect and append stderr to file 2>> filename.txt # Redirect both stdout and stderr to file &> filename
ouput of a program to be written to a file:
ls -l > ls-l.txt
'ls-l.txt' will be created and it will contain what you would see on the screen if you type the command 'ls -l' and execute it.
This will cause the stderr ouput of a program to be written to a file.
grep da * 2> grep-errors.txt
'grep-errors.txt' will be created and it will contain what you would see the stderr portion of the output of the 'grep da *' command.
stderr ouput of a program to be written to the same filedescriptor than stdout.
grep da * 1>&2
Here, the stdout portion of the command is sent to stderr, you may notice that in differen ways
stderr 2 stdout
This will cause the stderr ouput of a program to be written to the same filedescriptor than stdout.
grep * 2>&1
Here, the stderr portion of the command is sent to stdout, if you pipe to less, you'll see that lines that normally 'dissapear' (as they are written to stderr) are being kept now (because they're on stdout).
stderr and stdout 2 file
This will place every output of a program to a file. This is suitable sometimes for cron entries, if you want a command to pass in absolute silence.
rm -f $(find / -name core) &> /dev/null
Pipes let you use (very simple, I insist) the output of a program as the input of another one
This is very simple way to use pipes.
ls -l | sed -e "s/[aeio]/u/g"
Here, the following happens: first the command ls -l is executed, and it's output, instead of being printed, is sent (piped) to the sed program, which in turn, prints what it has to.
Here, the output of the program ls -l is sent to the grep program, which, in turn, will print lines which match the regex "\.txt$".
ls -l | grep "\.txt$"
You can use variables as in any programming languages. There are no data types. A variable in bash can contain a number, a character, a string of characters.
You have no need to declare a variable, just assigning a value to its reference will create it.
Hello World! using variables
#!/bin/bash STR="Hello World!" echo $STR
Then the VALUE of STR variable is retrieved by putting the '$' in at the beginning. Please notice (try it!) that if you don't use the '$' sign, the output of the program will be different, and probably not what you want it to be.
A very simple backup script with variables
#!/bin/bash OF=/var/my-backup-$(date +%Y%m%d).tgz tar -cZf $OF /home/me/
Notice the expression '$(date +%Y%m%d)'. If you run the script you'll notice that it runs the command inside the parenthesis, capturing its output.
echo $(ls)
Local (non Global) variables can be created by using the keyword local.
#!/bin/bash HELLO=Hello function hello { local HELLO=World echo $HELLO } echo $HELLO hello echo $HELLO
#!/bin/bash if [ "foo" = "foo" ]; then echo expression evaluated as true fi
#!/bin/bash if [ "foo" = "foo" ]; then echo expression evaluated as true else echo expression evaluated as false fi
#!/bin/bash T1="foo" T2="bar" if [ "$T1" = "$T2" ]; then echo expression evaluated as true else echo expression evaluated as false fi
iterare l'output di un comando
#!/bin/bash for i in $( ls ); do echo item: $i done
one liner:
for FILE in $(ls); do [COMMAND]; done for FILE in $(svn status | grep ? | grep php); do echo $FILE; done
do infinito con intervallo di 5 secondi
while [ 1 ]; do acpi -t; sleep 5; done
iterare una sequenza
#!/bin/bash for i in `seq 1 10`; do echo $i done
#!/bin/bash COUNTER=0 while [ $COUNTER -lt 10 ]; do echo The counter is $COUNTER let COUNTER=COUNTER+1 done
#!/bin/bash COUNTER=20 until [ $COUNTER -lt 10 ]; do echo COUNTER $COUNTER let COUNTER-=1 done
#!/bin/bash c=1 while [ $c -le 5 ] do echo "Welcone $c times" (( c++ )) done
Calling a function is just like calling another program, you just write its name.
Notice that a functions don't need to be declared in any specific order. function 'e' prints the first argument it receives. Arguments, within funtions, are treated in the same manner as arguments given to the script.
#!/bin/bash function quit { exit } function e { echo $1 } e Hello e World quit echo foo
select
#!/bin/bash OPTIONS="Hello Quit" select opt in $OPTIONS; do if [ "$opt" = "Quit" ]; then echo done exit elif [ "$opt" = "Hello" ]; then echo Hello World else clear echo bad option fi done
pass values via CLI. The expression in the first conditional tests if the program has received an argument ($1) and quits if it didn't, showing the user a little usage message.
#!/bin/bash if [ -z "$1" ]; then echo usage: $0 directory exit fi SRCD=$1 TGTD="/var/backups/" OF=home-$(date +%Y%m%d).tgz tar -cZf $TGTD$OF $SRCD
prompt the user for some input, and there are several ways to achive this. This is one of those ways:
#!/bin/bash echo Please, enter your name read NAME echo "Hi $NAME!"
read multiple values
#!/bin/bash echo Please, enter your firstname and lastname read FN LN echo "Hi! $LN, $FN !"
notify-send -i /usr/share/pixmaps/FreeMindWindowIcon.xpm "Take a walk"
On the command line (or a shell) try this:
echo 1 + 1
If you expected to see '2' you'll be disappointed. What if you want BASH to evaluate some numbers you have? The solution is this:
echo $((1+1))
This will produce a more 'logical' output. This is to evaluate an arithmetic expression. You can achieve this also like this:
echo $[1+1]
If you need to use fractions, or more math or you just want it, you can use bc to evaluate arithmetic expressions.
if i ran "echo $[3/4]" at the command prompt, it would return 0 because bash only uses integers when answering. If you ran "echo 3/4|bc -l", it would properly return 0.75.
In bash, the return value of a program(0, -1 etc) is stored in a special variable called $?.
#!/bin/bash cd /dada &> /dev/null echo rv: $? cd $(pwd) &> /dev/null echo rv: $?
Capturing a commands output
#!/bin/bash DBS=`mysql -uroot -e"show databases"` for b in $DBS ; do mysql -uroot -e"show tables from $b" done
You can use multiple files with the command source.
You can split up your scripts into files and "include" them with the source aka dot "." operator. The includes do not need to start with "#!/bin/bash", but they must either be in your PATH or have their PATH written exclusively in the main script.
A script that includes another script
#!/bin/bash source My_Other_Script.sh # include is in $PATH source /path/to/the/include/My_Other_Other_Script.sh # explicit PATH
(1) s1 = s2 (2) s1 != s2 (3) s1 < s2 (4) s1 > s2 (5) -n s1 (6) -z s1 (1) s1 matches s2 (2) s1 does not match s2 (3) __TO-DO__ (4) __TO-DO__ (5) s1 is not null (contains one or more characters) (6) s1 is null
Comparing two strings:
#!/bin/bash S1='string' S2='String' if [ $S1=$S2 ]; then echo "S1('$S1') is not equal to S2('$S2')" fi if [ $S1=$S1 ]; then echo "S1('$S1') is equal to S1('$S1')" fi
instead of use if [ $1 = $2 ] as if either $S1 or $S2 is empty, you will get a parse error: "$1"="$2" is better.
Arithmetic operators
-lt (<) -gt (>) -le (<=) -ge (>=) -eq (==) -ne (!=)
string concatenation:
A="X Y" A+="Z" echo "$A" foo="Hello" foo="$foo World" echo $foo bla=hello laber=kthx echo "${bla} ohai ${laber} bye"
printf -v a "%s" "my_var" foo=$(printf "%s World" "$(date)")
awk template:
var="Hello " foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
inline commands:
echo "The current time is `date`" echo "Current User: `echo $USER`"
multiline string:
__TMPL__="hello \ > world"
write/append multiline string to file
#!/bin/bash myvar="abcef" cat >/etc/myconfig.conf <<EOL line 1, ${myvar} EOL
append:
myvar="abcef" cat >>/etc/myconfig.conf <<EOL line 1, ${myvar} EOL
#!/bin/bash # renames.sh # basic file renamer criteria=$1 re_match=$2 replace=$3 for i in $( ls *$criteria* ); do src=$i tgt=$(echo $i | sed -e "s/$re_match/$replace/") mv $src $tgt done
#!/usr/bin/env php <?php /* your PHP script */ ?>
History expansion
!! = previous command
!$ = last word of previous command
!-n = nth previous command
!#$ = last word of current line
!
Brace Expansion: {a..b} = numbers a to b in order. {a,b,c} = words a, b, c. Useful for paths: touch /tmp/{foo,bar,baz}
Parameter Expansion:
Suppose that foo=/usr/local/blah.txt
${variable#word} = removes word from the beginning of variable. For example, ${foo#*/} = usr/local/blah.txt
${variableword} = same thing, but removes longest pattern matching word. For example, ${foo
*/} = blah.txt
${variable%word} = removes word from end of variable. For example: ${foo%.txt} = /usr/local/blah
${variable%%word} = same thing but longest matching suffix
Process Substitution: <(command) = treats the output of command as a file. diff -u <(ssh web{1,2} cat /etc/passwd)) shows you a unified diff between /etc/passwd on web1 and 2
console percent updater
for( $i=0; $i<100; $i++ ) {
sleep(1);
echo sprintf("\r%3d%% " , $i);
}
history, most issued commands
history | awk '{print $2}' | sort | uniq -c | sort -rn | head -20
http://bashish.sourceforge.net/
vi ~/.bashrc echo $PS1 \s-\v\$ \\u@\h \\W]\\$
# minimalist setting: export PS1="\\t \$" # more info: export PS1="[\\u@\\H \\W \\@]\\$" # red color promp export PS1="\e[0;31m[\u@\h \W]\$ \e[m "
# If id command returns zero, you've root access. if [ $(id -u) -eq 0 ]; then # you are root, set red colour prompt PS1="\\[$(tput setaf 1)\\]\\u@\\h:\\w #\\[$(tput sgr0)\\]" else # normal PS1="[\\u@\\h:\\w] $" fi
Just assign a new value to PS1:
using tput program to customize prompt:
export PS1="\[$(tput setaf 1)\]\u@\h:\w $ \[$(tput sgr0)\]"
function cprint() { local text="$2" local nc='\033[0m' case "$1" in black | bk) color="\033[0;30m";; red | r) color="\033[1;31m";; green | g) color="\033[1;32m";; yellow | y) color="\033[1;33m";; blue | b) color="\033[1;34m";; purple | p) color="\033[1;35m";; cyan | c) color="\033[1;36m";; gray | gr) color="\033[0;37m";; #*) esac printf "${color}${text}${nc}" } ##] cprint r "colorful!\n" cprint g "colorful!\n" cprint y "colorful!\n" cprint b "colorful!\n" cprint p "colorful!\n" cprint c "colorful!\n" function y_print() { # $1 = string TEXT="$1" COLOR='\033[1;33m' NC='\033[0m' printf "${COLOR}${TEXT}${NC}\n" } ##] y_print "This will be Yellow"