Zbiór przydatnych skryptów bash (i funkcji do użycia we własnych skryptach).
Spis treści
|
Wstęp
Tutaj notuję sobie różne skrypty i funkcje w języku bash.
Może kiedyś z tego się wykluje jakiś HowTo :).
Licencja
Źródeł na tej stronie można używać na dowolnej z licencji: LGPL, BSD, PublicDomain.
Podstawowe elementy konstrukcji skryptów
Nagówek
Na początku każdego skryptu należy umieścić:
#!/bin/bash
W kolejnych liniach , "#' oznacza iż dalsza część lini oznacza komentarz.
Lista parametrow
Pod zmienną $@ kryje się lista prametrów.
Ale uwaga jeżeli zawierają spację to przy użyciu:
list_params $@
parametry ze spacjami zostana rozbite na oddzielne.
Aby tego uniknąć trzeba ująć w cudzysłów t.j. {"$@"} (trochę tak jakbyśmy chcieli każdy z parametrów ująć w cudzysłów).
zip backup.zip "$@"
iterowanie po parametrach
Aby wkonac po wszystkich paramatrach polecenia jakies polecenie np. "echo" robimy:
while [ ! -z "$1" ]; do
echo $1
shift
done
Aby iterowac po tych elementach trójkami robimy:
#dopuki wartosc zwrocona przez shift jest prawda (tzn. "0")
ok=0
while [ $ok -ne 1 ]; do
echo $1 $2 $3
shift 3
ok=$?
done
funkcje
liczby_dwucyfrowe_od_00_do $max
#!/bin/bash
function liczby_dwucyfrowe_od_00_do
{
local max=$1
for (( i=0; i<=$max; i++ )) ; do
#leading zeros
i2=$(( $i + 100 ))
istr=${i2:1:2}
echo $istr
done
}
echo type max
read max
liczby_dwucyfrowe_od_00_do $max
Kiedy posiadamy w systemie program "seq"
function liczby_dwucyfrowe_od_00_do
{
seq -f '%02.0f' 0 $1
}
ew. "od-do"
function liczby_dwucyfrowe_od_do
{
seq -f '%02.0f' $1 $2
}
process_each_input_line_to_empty ( Przetwarzaj oddzielnie linie wejścia aż do pustej)
Przetwarzaj oddzielnie linie wejścia aż do pustej.
#Przetwarza kazda linie wejscia oddzielnie w petli - aż do pustej
function process_each_input_line_to_empty
{
read inputline
while [ ! -z "$inputline" ]; do
echo ' #### '$inputline' ### '
read inputline
done
}
Przykład użycia: liczby_dwucyfrowe_od_00_do 33 | process_each_input_line
A jak chcemy użyć jakiegoś polecenia na każdym z wierszy wejściowych to możemy się wspomóc AWK:
find | awk '{ system( "dirname \"" $0 "\"" ); }'
( Praktyczne użycie : zcat file_list_2007-10-23.txt.gz | grep -i amppz | awk '{ system( "dirname \"" $0 "\"" ); }' | uniq )
rename_to_fat_convention
Z czasem będzie rozbudowane. Narazie tam gdzie trzeba dla podanej listy plikow zamienia w nazwach ":" na ".".
function convert_file_names_to_fat_names
{
#dopuki wartosc zwrocona przez shift jest prawda (tzn. "0")
ok=0
while [ $ok -ne 1 ]; do
oldfn=$1
newfn=$( echo $oldfn | sed 's/:/./g' )
if [ "$newfn" != "$oldfn" ]; then
mv -v "$oldfn" "$newfn"
fi
shift 1
ok=$?
done
}
Przykład użycia
convert_file_names_to_fat_names *.jpg
gethtmltitle, geturltitle
gethtmltitle - pobiera tytuł strony html podanej na wejscie
geturltitle - pobiera tytuł strony html o podanym adresie
#gethtmltitle
#input : html code
function gethtmltitle {
gawk ' BEGIN { FS="</body>"; RS="</html>" }
/<title>/ {
$0=gensub("\n"," ","G");
print gensub("(.*)<title([^>]*)>([^<]*)(.*)", "\\3", "G" );
}
/<TITLE>/ {
$0=gensub("\n"," ","G");
print gensub("(.*)<TITLE([^>]*)>([^<]*)(.*)", "\\3", "G" );
}'
}
#geturltitle url
function geturltitle {
wget -o /dev/null -O - "$1" | gethtmltitle
}
Przykład użycia: geturltitle 'http://grzegorz.wierzowiecki.pl/'
Zobacz również: 2007-10 List html files by titles with Awk
dirmd5
Funkcja robi sume md5 dla zadanego katalogu i ja w nim umieszcza.
Dobre do uzycia w petli for po katalogach w katalogu.
function dirmd5 ()
{
currpwd=$PWD;
cd "$1";
md5sum_make_for_directory . >/tmp/"$1".md5;
mv /tmp/"$1".md5 ./;
cd "$currpwd"
}
Ale w większości przypadków wystarcza
find -type f -exec md5sum -b "{}" \;
checkmd5
Sprawdza sume md5 danego katalogu.
Zaklada istnienie w katalogu pliku o tej samej nazwie z rozszerzeniem ".md5".
function checkmd5 ()
{
currpwd=$PWD;
cd "$1";
md5sum -c "$1".md5;
cd "$currpwd"
}
cut_extension
Followinh script cuts only 3-4 letter extensions:
function cut_extension(){
local A="$1";
if echo "$A" | grep "\.[^.0-9]\{3,4\}$" > /dev/null
then A="$(echo "$A" | sed 's/\(^.*\)\.[^.]*/\1/')"
fi
echo $A;
}
Based on : http://lists.freebsd.org/pipermail/freebsd-questions/2003-October/021729.html
cut_last_letters
Paramteres:
- text
- how many letters to cut from end
function cut_last_letters(){ echo ${1:0:${#1}-$2}; }
get_last_letters
Parameters:
- text
- how many letters to get from end
function get_last_letters(){ echo ${1:${#1}-$2:$2}; }
get_first_letters
Parameters:
- text
- how many letters to get from beginning
function get_first_letters(){ echo ${1:0:$2}; }
cut_first_letters
Parameters:
- text
- how many letters to cut from beginning
function cut_first_letters(){ echo ${1:0,$2}; }
random_number
Parameters:
- from
- to
Generates random number between "from" and "to"
function random_number(){
local rv=`od -An -N4 -t u4 /dev/random`;
echo $[ ($rv%($2-$1+1)) + $1 ];
}
(To make it faster to generate a lot of such numbers, use pseudo-random generator "urandom" instead of "random")
Size_Of_Contents_Of_Compressed_Archive
[[code]
case ‘get_last_letters "$filename" 3` in
.gz)
gzip -l "$filename" | awk ’{print $2}' | grep -v uncompressed
;;
.7z)
7za -slt l "$filename" | grep '^Size =' | awk '{print $3}'
;;
esac
[[/code]]
Checks size of contents of archive in bytes
remove_extension
function remove_extension() {
sed 's/\(.*\)\..*/\1/'
}
misc
"Indirect References to Variables"
Taken from Advanced Bash Shell Scripting Guide - Indirect References to Variables.
Assume that the value of a variable is the name of a second variable. Is it somehow possible to retrieve the value of this second variable from the first one? For example, if a=letter_of_alphabet and letter_of_alphabet=z, can a reference to a return z? This can indeed be done, and it is called an indirect reference. It uses the unusual eval var1=\$$var2 notation.
a=letter_of_alphabet # Variable "a" holds the name of another variable.
letter_of_alphabet=z
echo
# Direct reference.
echo "a = $a" # a = letter_of_alphabet
# Indirect reference.
eval a=\$$a
echo "Now a = $a" # Now a = z
My (Grzegorz's) example :) :
x=5
v=x
eval echo \$$v
funkcje - przykłady dłuższych
intersection_of_files_lines()
Want to find lines in files that have in common? Use this:
#params: file1 file2 [file3 [file4 ... ] ]
#output: lines that are in common
function intersection_of_files_lines(){
if [ "$#" -eq 1 ]; then
sort -u "$1"
elif [ "$#" -eq 2 ]; then
(sort -u "$1";sort -u "$b")|sort|uniq -d
elif [ "$#" -ge 3 ]; then
local a="$1"
local b="$2"
shift 2
# make intersection of $a and $b. Then call again for intersection with rest.
intersection_of_files_lines <( (sort -u "$a";sort -u "$b")|sort|uniq -d) "$@"
fi
}
md5sum_make_for_stdin
Link : make_md5sum_for_directory.sh .
Skrypty / przykładowe użycia
Zamiania nazw plików na duże litery
Cel: zamiana nazw plików wykładXX.html na WYKADXX.html .
1. Zamiana z wykladXX.html na x_WYKADXX.HTML
for f in wyklad*.html ; do nf=$( echo $f | sed 's/.*/x_\U&/g' ); mv -v "$f" "$nf" ; done
2. Zamiana z x_WYKADXX.HTML na WYKADXX.html
@@++ Lista parametrow
Pod zmienną {{$@ kryje się lista prametrów.
Ale uwaga jeżeli zawierają spację to przy użyciu:
list_params $@
parametry ze spacjami zostana rozbite na oddzielne.
Aby tego uniknąć trzeba ująć w cudzysłów t.j. {"$@"} (trochę tak jakbyśmy chcieli każdy z parametrów ująć w cudzysłów).
zip backup.zip "$@"
iterowanie po parametrach
Aby wkonac po wszystkich paramatrach polecenia jakies polecenie np. "echo" robimy:
while [ ! -z "$1" ]; do
echo $1
shift
done
Aby iterowac po tych elementach trójkami robimy:
#dopuki wartosc zwrocona przez shift jest prawda (tzn. "0")
ok=0
while [ $ok -ne 1 ]; do
echo $1 $2 $3
shift 3
ok=$?
done