IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

http://mywiki.wooledge.org/BashPitfalls

Linux Professional Institute Certificate. LPIC-1

Lpic1 large.gif
Certificat LPIC-1
Examen: 102 (torneu a la resta de temes)
Fitxers: LPI105.1_ConfiguracioMidaShell.pdf (LPI105.1_ConfiguracioMidaShell.odp) (105.1 i 105.2 al mateix fitxer), UD_8_8_shell_bash.pdf, UD_8_9_program_bash.pdf (Apunts Eva Dominguez)
Objectius: http://www.lpi.org/eng/certification/the_lpic_program/lpic_1/exam_102_detailed_objectives
Dipòsit SVN: https://svn.projectes.lafarga.cat/svn/lpi/Materials/Examen_102/105.2
Usuari: anonymous
Paraula de pas: qualsevol paraula de pas

Contingut

Objectius del tema

105.2. Adaptar o escriure guions d'intèrpret d'ordres simples
Objective.jpg
  • Objectiu: Els candidats han de ser capaços d'adaptar guions de shell existents o escriure nous guions de BASH simples.
  • Pes: 4
060317 Icon - Theory of Knowledge v01 pdc.jpg

Àrees Clau de Coneixement:

Icon list.jpg

La següent és una llista parcial de fitxers, termes i utilitats utilitzades:

Text-editor.svg

Apunts: LPI 105.2. Adaptar o escriure guions d'intèrpret d'ordres simples

Plantilla per prendre apunts

Guions de l'interpret d'ordres

Un guió de l'interpret d'ordres (shell script) és un fitxer de text que conté ordres de l'interpret. Quan el camí del fitxer que conté el guió s'utilitza com primer argument durant la invocació de bash:

$ bash guió.sh

Aleshores bash llegeix les ordres del fitxer, les executa i retorna l'execució a l'interpret d'ordres original. Aquest mode d'operació és anomenat no interactiu. Si no es proporciona el camí complet del fitxer, primer busca el fitxer al directori de treball i si no el troba aleshores el busca a les carpetes de la variable d'entorn $PATH.

Quan bash executa un guió, estableix el paràmetre 0 al nom del guió i els paràmetres posicionals passen a ser els paràmetres (si s'utilitzen) que es passen al guió.

Intèrprets de guions. shebang

Consulteu shebang.

Propietaris i permisos d'execució dels guions de shell

Per tal de poder utilitzar un script cal que sigui executable. Podeu establir els permisos d'execució d'un script amb:

$ sudo chmod +x guio.sh

si sou superusuari o teniu permisos de superusuari (vegeu sudo). Si no sou superusuari només podreu canviar els permisos del fitxers que siguin de la vostra propietat (vegeu chown i ls) amb:

$ chmod +x guio.sh

Si només voleu que el fitxer sigui executables per al vostre usuari:

$ chmod u+x guio.sh

Cal tenir en compte que els guions de shell s'executen en una subshell. És a dir:

$ guio.sh arguments

Equival a:

$ bash filename arguments

De fet, també es pot executar explícitament un guió de shell mitjançant l'interpret adequat. Per a un guió de sh seria:

$ sh guio.sh

o per un de bash

$ bash guio.sh

NOTA: Aquesta forma d'executar un interpret d'ordres es anomenada forma no interactiva. Cal tenir en compte que d'aquesta forma no s'executen els fitxers de configuració de shell ni de login (/etc/profile o ~/.profile) ni de no-login (/etc/bash.bashrc o ~/.bashrc)

Consulteu l'article shebang per obtenir més informació sobre els intèrprets de shell.

També cal que tingueu en compte també el valor del PATH:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Que normalment (per raons de seguretat) no inclou el directori de treball (PWD o .). Aleshores per executar un guió de shell que es troba al directori de treball cal utilitzar el punt barra (slashdot):

$ ./fitxer.sh

Observeu que només podreu utilitzar el tabulador (autocompletar), si el fitxer és executable.

SUID

Consulteu SUID.

Execució de guions de shell. Paràmetres posicionals

Quan bash executa un guió, guarda el nom del guió al paràmetre especial 0 ($0) (normalment, en mode interactiu, aquest paràmetre conté el nom de l'interpret d'ordres que s'està executant). Els paràmetres posicionals són establerts segons els paràmetres que es passen al guió. De fet recordeu que:

$ ./guio.sh parametre1 parametre2 parametre3 parametre4...

Equival a:

$ bash guio.sh parametre1 parametre2 parametre3 parametre4...

Un paràmetre posicional és una paràmetre definit per un o més digits (1, 2, 3, ..., 10, 11, ...). Són establerts durant l'execució del guió però poden ser restarblerts mitjançant l'ordre interna set i esborrats amb shift. Per referir-se al paràmetre N utilitzem:

${N}

o

$N

Si N és un sol digit. Cal tenir en compte doncs que el paràmetre 10 s'hauria d'indicar amb:

${10}

Ordre shift

L'ordre shift n permet desplaçar els paràmetres posicionals n vegades. Si n no s’especifica es considera igual a 1: $1 torna el valor de $2, $2 torna el valor de $3, i així successivament.

Utilitzar paràmetres posicionals

Exemples:

Amb un loop a l'estil de C:

numargs=$#
for ((i=1 ; i <= numargs ; i++)); do
  echo "$1"
  shift
done

Un altre exemple:

for arg; do
  echo "$arg"
done

Un altre exemple:

while [ "$1" ]; do
  echo "$1"
  shift
done

s'atura però quan $1 és buit. Millor:

while [ "${1+defined}" ]; do
  echo "$1"
  shift
done

Com gestionar molts paràmetres posicionals o fins i tot una quantitat indefinida a priori de paràmetres, tenim:

$* i [[$@]

TODO:

Without being quoted (double-quoted), both have the same effect: All positional parameters from $1 to the last used one are expanded without any specials. A subsequent wordsplitting will recognize as much words as expanded before (i.e. it "doesn't preserve words").

When the $* special parameter is doublequoted, it expands to the equivalent of: "$1c$2c$3c$4c........$N", where 'c' is the first character of IFS.

But when the $@ special parameter is used inside doublequotes, it expands to the equivanent of...

"$1" "$2" "$3" "$4" ..... "$N"

...which exactly reflects all positional parameters like they were initially set and given to the script or the function. If you want to re-use your positional parameters to call another program (for example in a wrapper-script), then this is the choice for you, use the doublequoted "$@".

Well, let's just say: You almost always want "$@"! Range Of Positional Parameters

Es poden utilitzar arrays:

${@:START:COUNT}

${*:START:COUNT}

"${@:START:COUNT}"

"${*:START:COUNT}"

The rules for using @ or * and the quoting are the same as above. This will expand COUNT number of positional parameters starting at START. COUNT can be omitted (${@:START}), in this case all positional parameters beginning at START are expanded.

If START is negative, the positional parameters are numbered from the last one backwards.

COUNT may not be negative, so elements are always counted in the forward direction.

Example: START at the last positional parameter:

echo "${@: -1}"
V4: Attention: Since Bash 4, a START of 0 includes the special parameter $0, i.e. the shell name or whatever it's set to, when the positional parameters are in use. A START of 1 begins at $1. In Bash 3 and older, both 0 and 1 began at $1.

Setting Positional Parameters

Letting the caller set the positional parameters, by giving parameters on commandline, is not the only way to set them. The set builtin command can be used to "artificially" change the positional parameters from inside the script or function:

set "This is" my new "set of" positional parameters

# RESULTS IN
# $1: This is
# $2: my
# $3: new
# $4: set of
# $5: positional
# $6: parameters

It's wise to signal "end of options" when setting positional parameters this way. If not, dashes might be interpreted as option tag by set itself:

  1. both ways work, but behave different. See the article about the set command!

set -- ... set - ...

Exemples
while [ "${1+isset}" ]; do
  case "$1" in
    -x|--extmode)
      MY_EXTENDEDMODE=1
      shift
      ;;
    -u|--user)
      MY_USERNAME="$2"
      shift 2
      ;;
    -f|--configfile)
      MY_CONFIG="$2"
      shift 2
      ;;
    -h|--help)
      display_help # a function ;-)
      # no shifting needed here, we'll quit!
      exit
      ;;
    *)
      echo "Error: Unknown option: $1" >&2
      exit 1
      ;;
  esac
done

Millorat:

while [[ $1 = -* ]]; do
  case "$1" in
    -x|--extmode)
      MY_EXTENDEDMODE=1
      shift
      ;;
    -u|--user)
      MY_USERNAME="$2"
      shift 2
      ;;
    -f|--configfile)
      MY_CONFIG="$2"
      shift 2
      ;;
    -h|--help)
      display_help # a function ;-)
      # no shifting needed here, we'll quit!
      exit
      ;;
    *)
      echo "Error: Unknown option: $1" >&2
      exit 1
      ;;
  esac
done

echo "Processing files..."

for file; do
  echo "File: $arg"
  # ...
done

TODO:

Due to the shifting in the while-loop, the mass-arguments begin at $1, they're fully accessible by "$@" or for i.

Note the while-condition: It's not the test command, it's the conditional expression, since we do pattern matching. Filter unwanted options with a wrapper script

This simple wrapper allows to filter unwanted options (here: -a and –all for ls) out of the commandline. It reads the positional parameters and builds a (filtered) array out of them, then it calls ls with the new option set. It also respects the – as "end of options" for ls and doesn't change anything after it:

#!/bin/bash

# simple ls(1) wrapper that doesn't allow the -a option

EOO=0 # end of options reached

while [[ $1 ]]; do
if ! ((EOO)); then
  case "$1" in
    -[^-]*a*|-a?*)
      OPTIONS+=("${1//a}")
      shift
      ;;
    -a)
      shift
      ;;
    --all)
      shift
      ;;
    --)
      EOO=1
      OPTIONS+=("$1")
      shift
      ;;
    *)
      OPTIONS+=("$1")
      shift
      ;;
  esac
else
  OPTIONS+=("$1")
  # Another (worse) way of doing the same thing:
  # OPTIONS=("${OPTIONS[@]}" "$1")
  shift
fi
done

/bin/ls "${OPTIONS[@]}"

També podeu utilitzar getopts

getopts (llegir paràmetres posicionals tipus -f fitxer)

L'ordre getopts és una built-in command que permet operar còmodament amb els paràmetres que se li passen a un programa. S'utilitza en scripts de bash per tal de analitzar els paràmetres posicionals ("$@").

Els avantatges són;

  • No cal un programa extern per analitzar els paràmetres
  • Amb getopts guardarem els paràmetres a les variables de SHELL que desitgem
  • També hi ha un ordre anomenada getopt, getopts millora la funcionalitat.
  • Està definit al l'estàndard POSIX

IMPORTANT: Tingueu en compte que getopts no pot analitzar paràmetres llargs tipus GNU-style (--myoption) ni tampoc tipus XF86 (-myoption)

Vegem un exemple:

while getopts ":a:b" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      AISSET=TRUE
      A=$OPTARG
      ;;
    b)
      echo "-b was triggered" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
 done

Expliquem el codi: el bucle while executarà getopts de forma reiterada fins que s'acabin els arguments (obté un paràmetre i torna TRUE fins que no troba més paràmetres i torna false).

IMPORTANT: En el moment que es troba un paràmetre posicional que no comença per - (excepte si és l'argument d'un paràmetre anterior que si començava per -), getopt atura la seva execució

La sintaxi és:

getopts optstring name [args]

On:

  • optstring: permet especificar quina opció busquem i si la opció tindrà arguments extres (tipus -f fitxer)
  • name: és el nom de la variable de shell on s'anirà posant el valor del paràmetre llegit per getopts.
  • args: aquest paràmetre és opcional i només s'utilitza si els paràmetres que volem processar no són els posicionals. El valor per defecte és: "$@" . Vegeu getopts amb paràmetres no posicionals.

La sintaxi de optstring és força simple, per cada opció de caràcter que espereu indique el seu nom, per exemple si els paràmetres són:

-f -A -x

cal posar

getopts fAx VARNAME

Si espereu que una opció tingui un argument (per exemple -A argument) cal posar dos punts : després del caràcter que representa al paràmetre:

getopts fA:x VARNAME

Anem a provar el programa, si l'executeu:

$ ./getopts 

No troba cap paràmetre, no fa res (no entra dins del while en cap moment)

Paràmetres posicional incorrecte:

$ ./getopts -c
Invalid option: -c

es detecta i en aquest cas es finalitza el programa (exit).

$ ./getopts -a
Option -a requires an argument.

-a és un paràmetre esperat però que requereix d'arguments extres (hem posat al optstring el caràcter dos punts : després de la a). Noteu com fem una entra al case per a : que equival a aquest casos d'error i com utilitzem el mateix missatge d'error.

IMPORTANT: El primer caràcter que hem posat al optstring és els dos punts :, això fa que s'executi getopts en mode silenciós

Una execució correcta:

$ ./getopts -a asd
-a was triggered, Parameter: asd

compte que si el paràmetre es posa més d'un cop es llegira tants cops com calgui

$ ./getopts -a prova -a prova
-a was triggered, Parameter: prova
-a was triggered, Parameter: prova

Si no ho voleu així cal crear un comptador i controlar que no s'utilitzi més d'un cop.

L'exemple al trobar un paràmetre incorrecte s'atura tot i que la resta siguin correctes:

$ ./getopts -b -a prova -a prova 
Invalid option: -b

Fixeu-vos el següent cas:

$ ./getopts -a -a prova
-a was triggered, Parameter: -a

és correcte però potser el argument extra no és l'esperat?

Disposem de les següents variables:

  • OPTIND: Conté l'index del següent argument ha ser processat. Al inici del shell script s'inicialitza al valor 1. Si cal tornar a obtenir els paràmetres posicionals cal tornar a posar aquest valor a 1.
  • OPTARG: Depèn del mode, però normalment conté el argument extra de les opcions que s'indiquen com a opcions amb arguments extres. També conté el valor del caràcter en cas que sigui un caràcter invalid.
  • OPTERR: Cal mostrar els errors que trobi getopts?

Al manual de bash ($ man bash) podeu consultar la informació sobre getopts:

getopts optstring name [args]
  getopts is used by shell procedures to parse positional parameters.  optstring contains the option characters to be recognized; if a  char‐
  acter  is followed by a colon, the option is expected to have an argument, which should be separated from it by white space.  The colon and
  question mark characters may not be used as option characters.  Each time it is invoked, getopts places the next option in the shell  vari‐
  able  name, initializing name if it does not exist, and the index of the next argument to be processed into the variable OPTIND.  OPTIND is
  initialized to 1 each time the shell or a shell script is invoked.  When an option requires an argument, getopts places that argument  into
  the variable OPTARG.  The shell does not reset OPTIND automatically; it must be manually reset between multiple calls to getopts within the
  same shell invocation if a new set of parameters is to be used.

  When the end of options is encountered, getopts exits with a return value greater than zero.  OPTIND is set to the index of the first  non-
  option argument, and name is set to ?.

  getopts normally parses the positional parameters, but if more arguments are given in args, getopts parses those instead.
  getopts  can  report errors in two ways.  If the first character of optstring is a colon, silent error reporting is used.  In normal opera‐
  tion diagnostic messages are printed when invalid options or missing option arguments are encountered.  If the variable OPTERR is set to 0,
  no error messages will be displayed, even if the first character of optstring is not a colon.

  If  an  invalid  option  is  seen, getopts places ? into name and, if not silent, prints an error message and unsets OPTARG.  If getopts is
  silent, the option character found is placed in OPTARG and no diagnostic message is printed.

  If a required argument is not found, and getopts is not silent, a question mark (?) is placed in name, OPTARG is unset,  and  a  diagnostic
  message is printed.  If getopts is silent, then a colon (:) is placed in name and OPTARG is set to the option character found.

  getopts  returns  true if an option, specified or unspecified, is found.  It returns false if the end of options is encountered or an error
  occurs.

Altres ordres que també podeu utilitzar són:

Terminologia

Segons els següent exemple:

mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt

Anem a veure els tipus de paràmetres posicionals:

  • -x és una opció, un flag, un switch. Un sol caràcter precedit d'un guió (dash)
  • -f és també una opció però que té un argument addicional (l'argument de l'opció -f). L'argument opcional va tot seguit separat per un espai.
  • -r oco en aquest cas tot i que podria ser una opció amb arguments opcionals (això ho decideix el desenvolupador de l'aplicació) és tracta 'una opció simple sense més arguments.
  • ./foo.txt i ./bar.txt són la resta d'arguments i no tenen cap opció relacionada. S'anomenen mass-arguments. POSIX els anomena operands.

getopts és una eina molt útil per què permetrà que el vostre programa funcioni igual que a l'exemple anterior posant:

$ mybackup -xrf /etc/mybackup.conf ./foo.txt ./bar.txt

Les opcions tipus flag poden ser en minúscules o majúscules (són paràmetres diferents, és case sensitive) i també dígits. Es poden utilitzar altres caràcters però no es recomana.

getopts en mode silenciós

Recordeu la sintaxi:

getopts optstring VARNAME [args]

És el mode recomanat en scripts en producció (un cop acabat el desenvolupament), s'ha d'activar posant el caràcter : davant de optstring. Si no es fa així per defecte el mode és el mode VERBOSE, en aquest cas:

  • Es troba una opció invàlida: VARNAME s'estableix al valor ? i OPTARG no té cap valor
  • Es troba un paràmetre que requeria argument extra: VARNAME s'estableix al valor ? i OPTARG no té cap valor i es mostra un error

En canvi al mode silenciós:

  • Es troba una opció invàlida: VARNAME s'estableix al valor ? i OPTARG s'estableix al valor que ha definit l'usuari (tot i ser incorrecte)
  • Es troba un paràmetre que requeria argument extra: VARNAME s'estableix al valor : i OPTARG conté el caràcter del paràmetre que s'ha especificat.
getopts amb paràmetres propis (no posicionals)
while getopts :f:h opt "${MY_OWN_SET[@]}"; do
  ...
done

De fet per defecte getopts executa (lel tercer paràmetres de la sintaxi de getopts per defecte és "$@"):

getopts ... "$@"

Codi de sortida

El codi de sortida (en anglès exit status) és el valor retornat de l'última ordre executada (normalment s'obté mitjançant la crida de sistema waitpid)

Els valors dels codis de sortida estan entre 0 i 255.

El conveni és que un ordre amb codi de sortida 0 és un ordre executada correctament. Qualsevol altre codi de sortida indica un error.

La variable d'entorn $? conté sempre el codi de sortida de l'última ordre executada.

Si una ordre no es troba aleshores el codi de retorn és 127:

$ pepito
pepito: command not found
$ echo $?
127

Si l'ordre es trobada però no és executable retorna 126:

$ ./prova.sh
bash: ./prova.sh: Permission denied
$ echo $?
126

El codi de sortida pot ser utilitzat per expressions condicionals, com per exemple:

 $ pasd asd asd asd 
 No command 'pasd' found, did you mean:
  ...
 pasd: command not found
 $ if [[ "$?" != 0 ]]; then echo "error";fi
 error  
 

o fins i tot és utilitzat implícitament en llistes d'ordres OR (||) i AND (&&).

Totes les ordres internes retornen el codi d'error 2 per indicar un mal ús de l'ordre:

$ export -G adssaasd
bash: export: -G: invalid option
export: usage: export [-fn] [name[=value] ...] or export -p
$ echo $?
2

Sintaxi de l'interpret d'ordres

Tipus de variables

Arrays

Arrays associatius:

http://www.linuxjournal.com/content/bash-associative-arrays

Comentaris

Els comentaris es poden fer amb el símbol:

#

Aquest símbol ha de ser el primer exceptuant espais o tabuladors. Tot el que hi hagi al darrera d'aquest caràcter és ignorat per l'intèrpret d'ordres.

NOTA: No existeix cap caràcter o combinacions de caràcters que permetin fer comentaris multilínia

Cal tenir en compte que cal que estigui activada l'opció de l'intèrpret:

interactive_comments

per tal de poder utilitzar comentaris en un interpret d'ordres interactiu. Aquesta opció com la resta d'opcions de l'interpret es poden establir amb l'ordre interna shopt:

$ #prova

$ shopt -u interactive_comments
$ shopt -u | grep interactive
interactive_comments	off
$ #prova
#prova: command not found

Caràcters de cita (QUOTING)

Els caràcters de cita s’utilitzen per modificar la interpretació del shell d’altres caràcters. Així, un caràcter especial pot interpretar-se literalment i no de forma simbòlica. Això permet que certs programes i utilitats reinterpreten o estenguin els caràcters especials passats a la línia de comandes sense que els interpreti el propi shell.

Les comandes grep i find utilitzen caràcters de cita.

Els apòstrofs

El shell ignora tots els caràcters especials escrits entre apòstrofs.

Les cometes

Tots els caràcters especials entre cometes s’ignoren excepte $, ` i \:

La barra invertida o backslash(\)

Tot caràcter que segueix a la barra invertida perd el seu significat especial. La \ no produeix cap efecte si el caràcter següent no és un caràcter especial.

L’ús dels caràcters de cita permeten manipular arxius amb noms poc convencionals. Una vegada creats, s’han d’utilitzar amb molta prudència, especialment a l’hora d’esborrar.

Aquests caràcters de cita inhibeixen el significat de la tecla Intro que caracteritza el fi de la comanda; per això s’obté la presentació del prompt i és per aquesta raó que s'obté el PROMP secundari ($PS2) quan falta una cometa o un apòstrofe de tancament, o bé quan es col·loca una barra invertida al final de la línia:

$ ls \
> la
sortida de l'ordre ls -la
...

Paràmetres

Un paràmetre és una entitat que emmagatzema valors. Un paràmetre pot ser un nom, un número, un caràcter especial o una combinació dels anteriors.

NOTA: Una variable és un paràmetre que es denota per un nom. No anomenem variables als paràmetres posicionals ja que es denoten per números

Una variable té un valor i zero o més atributs. Els atributs s'estableixen amb la comanda interna declare.

Es considera que un paràmetre està establert si se li ha assignat un valor. El conjunt de caràcters (string) nul (null) és un valor vàlid i per tant una variable ha estat establerta només es pot desestablir amb l'ordre interna unset (no és el mateix establir-li el valor ="").

Les variables s'assignen de la següent forma:

name =[value ]

Si no es proporciona cap valor a la variable se li assigna el conjunt de caràcters null (null string).

NOTA: Cal tenir en compte que per defecte s'apliquen als valors tant les expansions, com les substitucions d'ordres, etc.... Per exemple:

$ nom=*
$ echo $nom

Si es volen utilitzar caràcters especials cl fer quoting:

$ nom1="*"
$ echo "$nom1"
*

Observeu que s'han posat entre cometes dobles fins i tot l'ús de a la variable a la línia de l'echo.

Us mostrarà els noms dels fitxers del directori de treball. Per tant es necessari utilitzar "quoting" si voleu guardar caràcters amb valors especials com l'asterisc (*):

Variables globals (variables d'entorn)

Les variables d'entorn es poden considerar com a variables globals. Consulteu variables d'entorn.

Variables locals

Es defineixen només per a l'interpret d'ordres que es troba en execució:

$ nom="Sergi Tur"
$ echo $nom
Sergi Tur

Les variables locals a diferència de les globals o d'entorn no s'exporten als processos fills:

$ nom="Sergi Tur"
$ echo $nom
Sergi Tur
$ bash
$ echo $nom

En canvi si s'exporta la variable amb export:

$ export nom="Sergi Tur"
$ echo $nom
Sergi Tur
$ bash
$ echo $nom
Sergi Tur

NOTA: Cal tenir en compte que global no implica que estigui disponible a totes les terminals. Depén del que s'estableixi als scripts de configuració d'inici bash

Comanda interna declare

L'ordre interna (builtin command) declare permet tenir un major control sobre la declaració de variables. La sintaxi és:

declare OPCIÓ(ns) VARIABLE=valor

La següent taula mostra les opcions:

Opció Descripció
-a La variable és un array
-f Només utilitza noms de funcions
-i La variable s'ha de tractar com un enter.
-p Mostra els atributs i els valors de cada variable
-r Crea una variable de només lectura (constant)
-r Crea una variable de només lectura (constant)
-r Crea una variable de només lectura (constant). No es poden modificat ni es pot utilitzar unset
-t Assigna a cada variable el atribut trace
-x Marca cada variable per tal de ser exportada a comandes subsegüents a través de l'entorn

NOTA: Observeu que no hi ha cap opció per declarar un string. Per defecte si no es diu res és l'atribut per defecte de les variables

Si s'utilitza + en comptes de - aleshores es desactiva l'atribut. Quan declare s'utilitza en un funció defineix una variable local a la funció.

Vegem alguns exemples. Si declarem una variable com un enter, aleshores certes operacions aritmètiques es poden realitzar sense utilitzar expr o let. Sense declaració:

$ n=6/3
$ echo "n = $n"
n = 6/3

En canvi:

$ declare -i n
$ n=6/3
$ echo "n = $n"
n = 2

Vegeu també typeset.

Comanda interna typeset

La sintaxi és molt similar a declare. Consulteu el manual de bash:

$ man bash

A la secció BUILTIN COMMANDS.

Vegeu també declare.

Constants

Es pot utilitzar readonly:

$ readonly OPCIÓ VARIABLE(s)

o

$ declare -r VARIABLE=VALOR

Les constants no es poden modificar. Per exemple:

$ readonly TUX=penguinpower
$ TUX=Mickeysoft
bash: TUX: readonly variable

Recursos:

Paràmetres de shell

La shell proporciona per defecte els següents paràmetres:

Paràmetres Bourne Shell:

CDPATH      A colon-separated list of directories used as a search path for the cd builtin
            command.
HOME        The current user’s home directory; the default for the cd builtin command. The
            value of this variable is also used by tilde expansion (see Section 3.5.2 [Tilde
            Expansion], page 19).
IFS         A list of characters that separate fields; used when the shell splits words as part
            of expansion.
MAIL        If this parameter is set to a filename and the MAILPATH variable is not set, Bash
            informs the user of the arrival of mail in the specified file.
MAILPATH    A colon-separated list of filenames which the shell periodically checks for new
            mail. Each list entry can specify the message that is printed when new mail
            arrives in the mail file by separating the file name from the message with a ‘?’.
            When used in the text of the message, $_ expands to the name of the current
            mail file.
OPTARG      The value of the last option argument processed by the getopts builtin.
OPTIND      The index of the last option argument processed by the getopts builtin.
PATH        A colon-separated list of directories in which the shell looks for commands. A
            zero-length (null) directory name in the value of PATH indicates the current
            directory. A null directory name may appear as two adjacent colons, or as an
            initial or trailing colon.
PS1         The primary prompt string. The default value is ‘\s-\v\$ ’. See Section 6.9
            [Printing a Prompt], page 85, for the complete list of escape sequences that are
            expanded before PS1 is displayed.
PS2         The secondary prompt string. The default value is ‘> ’.

Variables bash:

BASH        The full pathname used to execute the current instance of Bash.
BASHPID   Expands to the process id of the current Bash process. This differs from $$
         under certain circumstances, such as subshells that do not require Bash to be
         re-initialized.
BASH_ALIASES
          An associative array variable whose members correspond to the internal list
         of aliases as maintained by the alias builtin (see Section 4.1 [Bourne Shell
         Builtins], page 37). Elements added to this array appear in the alias list; un-
         setting array elements cause aliases to be removed from the alias list.
BASH_ARGC
         An array variable whose values are the number of parameters in each frame of
         the current bash execution call stack. The number of parameters to the current
         subroutine (shell function or script executed with . or source) is at the top of
         the stack. When a subroutine is executed, the number of parameters passed
         is pushed onto BASH_ARGC. The shell sets BASH_ARGC only when in extended
         debugging mode (see Section 4.3.2 [The Shopt Builtin], page 56 for a description
         of the extdebug option to the shopt builtin).
BASH_ARGV
         An array variable containing all of the parameters in the current bash execution
         call stack. The final parameter of the last subroutine call is at the top of the
         stack; the first parameter of the initial call is at the bottom. When a subroutine
         is executed, the parameters supplied are pushed onto BASH_ARGV. The shell
         sets BASH_ARGV only when in extended debugging mode (see Section 4.3.2 [The
         Shopt Builtin], page 56 for a description of the extdebug option to the shopt
         builtin).
BASH_CMDS
         An associative array variable whose members correspond to the internal hash
         table of commands as maintained by the hash builtin (see Section 4.1 [Bourne
         Shell Builtins], page 37). Elements added to this array appear in the hash table;
         unsetting array elements cause commands to be removed from the hash table.
BASH_COMMAND
         The command currently being executed or about to be executed, unless the
         shell is executing a command as the result of a trap, in which case it is the
         command executing at the time of the trap.
BASH_ENV  If this variable is set when Bash is invoked to execute a shell script, its value is
         expanded and used as the name of a startup file to read before executing the
         script. See Section 6.2 [Bash Startup Files], page 75.
BASH_EXECUTION_STRING
         The command argument to the ‘-c’ invocation option.
BASH_LINENO
         An array variable whose members are the line numbers in source files corre-
         sponding to each member of FUNCNAME. ${BASH_LINENO[$i]} is the line
         number in the source file where ${FUNCNAME[$i]} was called (or ${BASH_
         LINENO[$i-1]} if referenced within another shell function). The corresponding
         source file name is ${BASH_SOURCE[$i]}. Use LINENO to obtain the current line
         number.
BASH_REMATCH
          An array variable whose members are assigned by the ‘=~’ binary operator
          to the [[ conditional command (see Section 3.2.4.2 [Conditional Constructs],
          page 10). The element with index 0 is the portion of the string matching the
          entire regular expression. The element with index n is the portion of the string
          matching the nth parenthesized subexpression. This variable is read-only.
BASH_SOURCE
          An array variable whose members are the source filenames corresponding to the
          elements in the FUNCNAME array variable.
BASH_SUBSHELL
          Incremented by one each time a subshell or subshell environment is spawned.
          The initial value is 0.
BASH_VERSINFO
          A readonly array variable (see Section 6.7 [Arrays], page 82) whose members
          hold version information for this instance of Bash. The values assigned to the
          array members are as follows:
          BASH_VERSINFO[0]
                       The major version number (the release).
          BASH_VERSINFO[1]
                       The minor version number (the version).
          BASH_VERSINFO[2]
                       The patch level.
          BASH_VERSINFO[3]
                       The build version.
          BASH_VERSINFO[4]
                       The release status (e.g., beta1).
          BASH_VERSINFO[5]
                       The value of MACHTYPE.
BASH_VERSION
          The version number of the current instance of Bash.

COLUMNS   Used by the select builtin command to determine the terminal width when
          printing selection lists. Automatically set upon receipt of a SIGWINCH.
COMP_CWORD
          An index into ${COMP_WORDS} of the word containing the current cursor po-
          sition. This variable is available only in shell functions invoked by the pro-
          grammable completion facilities (see Section 8.6 [Programmable Completion],
          page 117).
COMP_LINE
          The current command line. This variable is available only in shell functions
          and external commands invoked by the programmable completion facilities (see
          Section 8.6 [Programmable Completion], page 117).
COMP_POINT
          The index of the current cursor position relative to the beginning of the current
          command. If the current cursor position is at the end of the current command,
          the value of this variable is equal to ${#COMP_LINE}. This variable is available
          only in shell functions and external commands invoked by the programmable
          completion facilities (see Section 8.6 [Programmable Completion], page 117).
COMP_TYPE
          Set to an integer value corresponding to the type of completion attempted that
          caused a completion function to be called: TAB, for normal completion, ‘?’, for
          listing completions after successive tabs, ‘!’, for listing alternatives on partial
          word completion, ‘@’, to list completions if the word is not unmodified, or ‘%’, for
          menu completion. This variable is available only in shell functions and external
          commands invoked by the programmable completion facilities (see Section 8.6
          [Programmable Completion], page 117).
COMP_KEY   The key (or final key of a key sequence) used to invoke the current completion
          function.
COMP_WORDBREAKS
          The set of characters that the Readline library treats as word separators when
          performing word completion. If COMP_WORDBREAKS is unset, it loses its special
          properties, even if it is subsequently reset.
COMP_WORDS
          An array variable consisting of the individual words in the current command
          line. The line is split into words as Readline would split it, using COMP_
          WORDBREAKS as described above. This variable is available only in shell func-
          tions invoked by the programmable completion facilities (see Section 8.6 [Pro-
          grammable Completion], page 117).
COMPREPLY
          An array variable from which Bash reads the possible completions generated
          by a shell function invoked by the programmable completion facility (see Sec-
          tion 8.6 [Programmable Completion], page 117).
DIRSTACK   An array variable containing the current contents of the directory stack. Direc-
          tories appear in the stack in the order they are displayed by the dirs builtin.
          Assigning to members of this array variable may be used to modify directories
          already in the stack, but the pushd and popd builtins must be used to add
          and remove directories. Assignment to this variable will not change the cur-
          rent directory. If DIRSTACK is unset, it loses its special properties, even if it is
          subsequently reset.
EMACS      If Bash finds this variable in the environment when the shell starts with value
          ‘t’, it assumes that the shell is running in an emacs shell buffer and disables
          line editing.
EUID       The numeric effective user id of the current user. This variable is readonly.
FCEDIT     The editor used as a default by the ‘-e’ option to the fc builtin command.
FIGNORE    A colon-separated list of suffixes to ignore when performing filename comple-
          tion. A file name whose suffix matches one of the entries in FIGNORE is excluded
          from the list of matched file names. A sample value is ‘.o:~’
FUNCNAME   An array variable containing the names of all shell functions currently in the
          execution call stack. The element with index 0 is the name of any currently-
          executing shell function. The bottom-most element is "main". This variable
          exists only when a shell function is executing. Assignments to FUNCNAME have
          no effect and return an error status. If FUNCNAME is unset, it loses its special
          properties, even if it is subsequently reset.
GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames to be ignored
          by filename expansion. If a filename matched by a filename expansion pattern
          also matches one of the patterns in GLOBIGNORE, it is removed from the list of
          matches.
GROUPS     An array variable containing the list of groups of which the current user is a
          member. Assignments to GROUPS have no effect and return an error status. If
          GROUPS is unset, it loses its special properties, even if it is subsequently reset.
histchars
          Up to three characters which control history expansion, quick substitution, and
          tokenization (see Section 9.3 [History Interaction], page 125). The first charac-
          ter is the history expansion character, that is, the character which signifies the
          start of a history expansion, normally ‘!’. The second character is the character
          which signifies ‘quick substitution’ when seen as the first character on a line,
          normally ‘^’. The optional third character is the character which indicates that
          the remainder of the line is a comment when found as the first character of a
          word, usually ‘#’. The history comment character causes history substitution
          to be skipped for the remaining words on the line. It does not necessarily cause
          the shell parser to treat the rest of the line as a comment.
HISTCMD    The history number, or index in the history list, of the current command. If
          HISTCMD is unset, it loses its special properties, even if it is subsequently reset.
HISTCONTROL
          A colon-separated list of values controlling how commands are saved on the
          history list. If the list of values includes ‘ignorespace’, lines which begin with
          a space character are not saved in the history list. A value of ‘ignoredups’
          causes lines which match the previous history entry to not be saved. A value
          of ‘ignoreboth’ is shorthand for ‘ignorespace’ and ‘ignoredups’. A value of
          ‘erasedups’ causes all previous lines matching the current line to be removed
          from the history list before that line is saved. Any value not in the above
          list is ignored. If HISTCONTROL is unset, or does not include a valid value, all
          lines read by the shell parser are saved on the history list, subject to the value
          of HISTIGNORE. The second and subsequent lines of a multi-line compound
          command are not tested, and are added to the history regardless of the value
          of HISTCONTROL.
HISTFILE   The name of the file to which the command history is saved. The default value
          is ‘~/.bash_history’.
HISTFILESIZE
          The maximum number of lines contained in the history file. When this variable
          is assigned a value, the history file is truncated, if necessary, by removing the
          oldest entries, to contain no more than that number of lines. The history file is
          also truncated to this size after writing it when an interactive shell exits. The
          default value is 500.
HISTIGNORE
          A colon-separated list of patterns used to decide which command lines should
          be saved on the history list. Each pattern is anchored at the beginning of the
          line and must match the complete line (no implicit ‘*’ is appended). Each
          pattern is tested against the line after the checks specified by HISTCONTROL
          are applied. In addition to the normal shell pattern matching characters, ‘&’
          matches the previous history line. ‘&’ may be escaped using a backslash; the
          backslash is removed before attempting a match. The second and subsequent
          lines of a multi-line compound command are not tested, and are added to the
          history regardless of the value of HISTIGNORE.
          HISTIGNORE subsumes the function of HISTCONTROL. A pattern of ‘&’ is identical
          to ignoredups, and a pattern of ‘[ ]*’ is identical to ignorespace. Combining
          these two patterns, separating them with a colon, provides the functionality of
          ignoreboth.
HISTSIZE   The maximum number of commands to remember on the history list. The
          default value is 500.
HISTTIMEFORMAT
          If this variable is set and not null, its value is used as a format string for
          strftime to print the time stamp associated with each history entry displayed
          by the history builtin. If this variable is set, time stamps are written to the
          history file so they may be preserved across shell sessions. This uses the history
          comment character to distinguish timestamps from other history lines.
HOSTFILE   Contains the name of a file in the same format as ‘/etc/hosts’ that should
          be read when the shell needs to complete a hostname. The list of possible
          hostname completions may be changed while the shell is running; the next time
          hostname completion is attempted after the value is changed, Bash adds the
          contents of the new file to the existing list. If HOSTFILE is set, but has no value,
          Bash attempts to read ‘/etc/hosts’ to obtain the list of possible hostname
          completions. When HOSTFILE is unset, the hostname list is cleared.
HOSTNAME   The name of the current host.
HOSTTYPE   A string describing the machine Bash is running on.
IGNOREEOF
          Controls the action of the shell on receipt of an EOF character as the sole input.
          If set, the value denotes the number of consecutive EOF characters that can be
          read as the first character on an input line before the shell will exit. If the
          variable exists but does not have a numeric value (or has no value) then the
          default is 10. If the variable does not exist, then EOF signifies the end of input
          to the shell. This is only in effect for interactive shells.
INPUTRC    The name of the Readline initialization file, overriding the default of
          ‘~/.inputrc’.
LANG       Used to determine the locale category for any category not specifically selected
          with a variable starting with LC_.
LC_ALL     This variable overrides the value of LANG and any other LC_ variable specifying
          a locale category.
LC_COLLATE
          This variable determines the collation order used when sorting the results of
          filename expansion, and determines the behavior of range expressions, equiv-
          alence classes, and collating sequences within filename expansion and pattern
          matching (see Section 3.5.8 [Filename Expansion], page 24).
LC_CTYPE   This variable determines the interpretation of characters and the behavior of
          character classes within filename expansion and pattern matching (see Sec-
          tion 3.5.8 [Filename Expansion], page 24).
LC_MESSAGES
          This variable determines the locale used to translate double-quoted strings pre-
          ceded by a ‘$’ (see Section 3.1.2.5 [Locale Translation], page 7).
LC_NUMERIC
          This variable determines the locale category used for number formatting.
LINENO     The line number in the script or shell function currently executing.
LINES      Used by the select builtin command to determine the column length for print-
          ing selection lists. Automatically set upon receipt of a SIGWINCH.
MACHTYPE   A string that fully describes the system type on which Bash is executing, in the
          standard gnu cpu-company-system format.
MAILCHECK
          How often (in seconds) that the shell should check for mail in the files specified
          in the MAILPATH or MAIL variables. The default is 60 seconds. When it is time
          to check for mail, the shell does so before displaying the primary prompt. If
          this variable is unset, or set to a value that is not a number greater than or
          equal to zero, the shell disables mail checking.
OLDPWD     The previous working directory as set by the cd builtin.
OPTERR     If set to the value 1, Bash displays error messages generated by the getopts
          builtin command.
OSTYPE     A string describing the operating system Bash is running on.
PIPESTATUS
          An array variable (see Section 6.7 [Arrays], page 82) containing a list of exit sta-
          tus values from the processes in the most-recently-executed foreground pipeline
          (which may contain only a single command).
POSIXLY_CORRECT
         If this variable is in the environment when bash starts, the shell enters posix
         mode (see Section 6.11 [Bash POSIX Mode], page 87) before reading the startup
         files, as if the ‘--posix’ invocation option had been supplied. If it is set while
         the shell is running, bash enables posix mode, as if the command
                set -o posix
         had been executed.
PPID      The process id of the shell’s parent process. This variable is readonly.
PROMPT_COMMAND
         If set, the value is interpreted as a command to execute before the printing of
         each primary prompt ($PS1).
PROMPT_DIRTRIM
         If set to a number greater than zero, the value is used as the number of trailing
         directory components to retain when expanding the \w and \W prompt string
         escapes (see Section 6.9 [Printing a Prompt], page 85). Characters removed are
         replaced with an ellipsis.
PS3       The value of this variable is used as the prompt for the select command. If
         this variable is not set, the select command prompts with ‘#? ’
PS4       The value is the prompt printed before the command line is echoed when the ‘-x’
         option is set (see Section 4.3.1 [The Set Builtin], page 53). The first character
         of PS4 is replicated multiple times, as necessary, to indicate multiple levels of
         indirection. The default is ‘+ ’.
         The current working directory as set by the cd builtin.
PWD
RANDOM    Each time this parameter is referenced, a random integer between 0 and 32767
         is generated. Assigning a value to this variable seeds the random number gen-
         erator.
REPLY     The default variable for the read builtin.
SECONDS   This variable expands to the number of seconds since the shell was started.
         Assignment to this variable resets the count to the value assigned, and the
         expanded value becomes the value assigned plus the number of seconds since
         the assignment.
SHELL     The full pathname to the shell is kept in this environment variable. If it is not
         set when the shell starts, Bash assigns to it the full pathname of the current
         user’s login shell.
SHELLOPTS
         A colon-separated list of enabled shell options. Each word in the list is a valid
         argument for the ‘-o’ option to the set builtin command (see Section 4.3.1 [The
         Set Builtin], page 53). The options appearing in SHELLOPTS are those reported
         as ‘on’ by ‘set -o’. If this variable is in the environment when Bash starts up,
         each shell option in the list will be enabled before reading any startup files.
         This variable is readonly.
SHLVL      Incremented by one each time a new instance of Bash is started. This is intended
          to be a count of how deeply your Bash shells are nested.
TIMEFORMAT
          The value of this parameter is used as a format string specifying how the tim-
          ing information for pipelines prefixed with the time reserved word should be
          displayed. The ‘%’ character introduces an escape sequence that is expanded to
          a time value or other information. The escape sequences and their meanings
          are as follows; the braces denote optional portions.
          %%            A literal ‘%’.
          %[p ][l]R The elapsed time in seconds.
          %[p ][l]U The number of CPU seconds spent in user mode.
          %[p ][l]S The number of CPU seconds spent in system mode.
          %P            The CPU percentage, computed as (%U + %S) / %R.
          The optional p is a digit specifying the precision, the number of fractional digits
          after a decimal point. A value of 0 causes no decimal point or fraction to be
          output. At most three places after the decimal point may be specified; values
          of p greater than 3 are changed to 3. If p is not specified, the value 3 is used.
          The optional l specifies a longer format, including minutes, of the form
          MM mSS.FFs. The value of p determines whether or not the fraction is
          included.
          If this variable is not set, Bash acts as if it had the value
                  $’\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS’
          If the value is null, no timing information is displayed. A trailing newline is
          added when the format string is displayed.
TMOUT      If set to a value greater than zero, TMOUT is treated as the default timeout for the
          read builtin (see Section 4.2 [Bash Builtins], page 43). The select command
          (see Section 3.2.4.2 [Conditional Constructs], page 10) terminates if input does
          not arrive after TMOUT seconds when input is coming from a terminal.
          In an interactive shell, the value is interpreted as the number of seconds to wait
          for input after issuing the primary prompt when the shell is interactive. Bash
          terminates after that number of seconds if input does not arrive.
TMPDIR     If set, Bash uses its value as the name of a directory in which Bash creates
          temporary files for the shell’s use.
UID        The numeric real user id of the current user. This variable is readonly.

Paràmetres especials

Els següents paràmetres són especials i només es poden consultar i no pas establir o modificar:

*          Mostra tots els paràmetres posicionals començant per 1. Si no s'estableix la variable 
           IFS es mostren els paràmetres separats per espais.
@          Mostra tots els paràmetres posicionals començant per 1. Si no s'estableix la variable IFS
           "$@" s'expandeix a "$1" "$2"
#          Mostra el número de paràmetres posicionals.
?          Mostra el codi de sortida de l'última ordre executada en primer terme
-          (hyphen) Mostra les opcions que s'estan utilitzant en el moment de la invocació
$          Mostra el PID del procés en execució. En una subshell mostra el procés/guió que ha invocat la 
           subshell i no pas el PID de la subshell. En shells interactives mostra el PID de la shell.
!          Mostra el PID de l'últim procés executat en segon terme
0          Mostra el nom l'interpret d'ordres que s'està utilitzant (shell interactiu) o el nom de l'script
           en cas de no ser un shell interatiu. Si s'utilitza -c aleshores mostra el procés invocat després

Expressions

Expressions numèriques

Consulteu LPI_105.1._Configuració_a_mida_i_ús_de_l'entorn_shell#Expressions

Els operadors aritmètics que es poden utilitzar són:

id++ Post_increment. S'augmenta en un el valor després d'utilitzar-lo.
id-- Post_decrement. Es disminueix en un el valor després d'utilitzar-lo
++id Pre-increment. S'augmenta en un el valor abans d'utilitzar-lo.
--id Pre-decrement. Es disminueix en un el valor després d'utilitzar-lo
!~   Negació lògica i negació bitwise
**   Exponenciació
*    Multiplicació
/    Divisió
%    Resta de la divisió
+    Suma
-    Resta
<<   Left Bitwise Shift
>>   Right Bitwise Shift
<    Menor que
<=   Menor igual que
>    Menor que
>=   Major igual que
==   Igual
!=   No igual
&    Bitwise AND
^    Bitwise exclusive OR
|'   Bitwise OR
&&   Logical AND
'||  Logical OR
expr ? expr : expr Operador condicional

Assignacions

 
 = 
 *= 
 /= 
 %= 
 += 
 -= 
 <<= 
 >>= 
 &= 
 ^= 
 |=
 

Expressions condicionals

Bash proporciona una serie d'expressions condicionals relacionades amb fitxers

-a fitxer        cert si el fitxer existeix.
-b fitxer        cert si el fitxer existeix i és un fitxer especial de bloc.
-c fitxer        cert si el fitxer existeix i és un fitxer especial de caràcter.
-d fitxer        cert si el fitxer existeix i és un directori.
-e fitxer        cert si el fitxer existeix.
-f fitxer        cert si el fitxer existeix i és un fitxer regular.
-g fitxer        cert si el fitxer existeix i el set-group-id està establert.
-h fitxer        cert si el fitxer existeix i és un enllaç simbòlic
-k fitxer        cert si el fitxer existeix i el sticky-bit està establert.
-p fitxer        cert si el fitxer existeix i és un conducte amb nom (named pipe (FIFO)).
-r fitxer        cert si el fitxer existeix i és llegible.
-s fitxer        cert si el fitxer existeix i té una mida diferent de zero.
-t fd            cert si el descriptor de fitxer existeix i està obert i es refereix a una terminal.
-u fitxer        cert si el fitxer existeix i el set-user-id està establert. 
-w fitxer        cert si el fitxer existeix i és modificable.
-x fitxer        cert si el fitxer existeix i és executable.
-O fitxer        cert si el fitxer existeix i és propietat del effective user id.
-G fitxer        cert si el fitxer existeix i és propietat del effective group id.
-L fitxer        cert si el fitxer existeix i és un enllaç simbòlic
-S fitxer        cert si el fitxer existeix i és un endoll (socket).
-N fitxer        cert si el fitxer existeix i ha estat modificat des de l'últim cop que es va llegir.
file1 -nt file2  cert si el fitxer 1 és més nou que el fitxer2 (segons la data de modificació)
file1 -ot file2  cert si el fitxer 1 és més vell que el fitxer2 o sí el fitxer2 existeix i el fitxer1 no.
file1 -ef file2  sí es refereixen al mateix dispositiu o tenen el mateix inode.  

Altres expressions condicionals:

-o optname            cert si l'opció de shell optname està establerta.
-z string             cert si la mida de l'string és zero
-n string             cert si la mida de l'string és diferents de zero
string1 == string2    cert si dos strings són iguals (també se pot utilitzar =)
string1 != string2    cert sí dos strings no són iguals 
string1 < string2     cert si l'string1 s'ordena lexicogràficament abans que l'string2
string1 > string2     cert si l'string1 s'ordena lexicogràficament després que l'string2

Operadors de comparació

arg1 OP arg2

On OP:

  • -eq: igual (equal)
  • -ne: no igual (not equal)
  • -lt: menys que (less than)
  • -le: menys que o igual (less than or equal)
  • -gt: més gran que (greater than)
  • -ge: més gran que o igual (greater than or equal)

Combinacions d'expressions

  • ! expressió; Retorna cert si la expressió és falsa, i fals si és certa:
  • expressió1 –a expressió2: -a (“and”) representa el “i lògic” entre expressió1 i expressió2:
       “Si /etc és un directori I la variable $valor és igual a 12”.
  • expressió1 –o expressió2: -o (“or”) representa el “o lògic” entre expressió1 i expressió2:
       “Si /etc és un directori O la variable $valor és igual a 12”.
  • \( expressió \): Es poden agrupar vàries expressions per evitar ambigüetats en el camp de l’aplicació de !, -a i –o:

NOTA: Les barres invertides són necessàries per interpretació dels parèntesis per part del shell.

ordre test

Serveix per provar les expressions comentades en apartats anteriors. El codi de retorn ( exit status) és el resultat d'avaluar una expressió. Per exemple:

$ test -e /etc/network/interfaces
$ echo $?
0
$ test -e /etc/network/interfacesads
$ echo $?
1

Consulteu:

$ man test

Com una referència important (conjuntament amb $ man bash) per a saber les expressions possibles.

Vegeu també LPI_105.2._Adaptar_o_escriure_guions_d'intèrpret_d'ordres_simples#Expressions_condicionals

Operacions amb Strings

Obtenir la mida d'un string

Podeu utilitzar:

${#string}
expr length $string
expr "$string" : '.*'

Exemple:

stringZ=abcABC123ABCabc

echo ${#stringZ}                 # 15
echo `expr length $stringZ`      # 15
echo `expr "$stringZ" : '.*'`    # 15

Obtenir un substring

Podeu utilitzar:

${string:position}

o

${string:position:length}

NOTA: If the $string parameter is "*" or "@", then this extracts the positional parameters, [1] starting at $position.

Exemples:

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                            # abcABC123ABCabc
echo ${stringZ:1}                            # bcABC123ABCabc
echo ${stringZ:7}                            # 23ABCabc
echo ${stringZ:7:3}                          # 23A
                                             # Three characters of substring.
# Is it possible to index from the right end of the string?
       
echo ${stringZ:-4}                           # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . .

echo ${stringZ:(-4)}                         # Cabc 
echo ${stringZ: -4}                          # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.


Capitalitzar la primera lletra

Podeu utilitzar l'operador ^ de la següent manera ${var^}:

$ PROVA=hola
$ echo ${PROVA^}
Hola

NOTA: En anglès capitalize

Estructures de control

Condicionals

if

La sintaxi és:

if test-commands ; then
      consequent-commands ;
[elif more-test-commands ; then
     more-consequents ;]
[else alternate-consequents ;]
fi

S'executa:

test-commands

i si el codi de retorn és zero s'executa la llista de comandes:

consequent-commands;

Si retorna un valor diferent de zero, aleshores s'executa

elif

si es cumpleixen:

more-test-commands

Per a tota la resta:

alternate-consequents

NOTA: Podeu consultar exemples de test-commands a Expressions condicionals

Vegem un exemple:

#!/bin/bash
T1="foo"
T2="bar"
if [ "$T1" = "$T2" ]; then
   echo expression evaluated as true
else
   echo expression evaluated as false
fi

IMPORTANT: Cal respectar els espais dins de la expressió condicional [[ expression ]]

case

La sintaxi és:

      case word in [ [(] pattern [| pattern ]...) command-list ;;]... esac

Si la paraula word compleix amb un patró aleshores s'executa un conjunt d'ordres especific. Es poden especificar tants patrons com es cregui convenient.

El patró pot contenir diferents opcions separades per | i sempre acaba en ).

Vegem un exemple:

echo -n "Enter the name of an animal: "
read ANIMAL
echo -n "The $ANIMAL has "
case $ANIMAL in
         horse | dog | cat) echo -n "four";;
         man | kangaroo ) echo -n "two";;
         *) echo -n "an unknown number of";;
esac
echo " legs."

Si es troba l'operador:

;;

Aleshores no s'intenta comprovar cap altre dels casos.

Si s'utilitza:

;&

Aleshores es continua l'execució a partir del següent cas.

Si s'utilitza:

;;&

Aleshores es continua l'execució a partir del següent cas si es compleix amb el patró especificat.

Switch retorna zero si no coincideix amb cap patró i si coincideix amb algun patró retorna el codi de retorn de la llista de comandes executada (si és llista normal tornarà el codi de retorn de l'última comanda)

select

NOTA: Aquesta secció està dedicada a la construcció select de bash. Si busqueu el SELECT de SQL consulteu SELECT

La construcció select permet generar fàcilment menús. La sintaxi és similar a for:

select variable [in list]
 do
  command...
  break
 done 

Vegem un exemple:

$ joe selecciona.sh
#!/bin/bash

PS3='Choose your favorite vegetable: ' # Sets the prompt string.
                                       # Otherwise it defaults to #? .

echo 

select vegetable in "beans" "carrots" "potatoes" "onions" "rutabagas"
do
  echo
  echo "Your favorite veggie is $vegetable."
  echo
  break  # What happens if there is no 'break' here?
done
exit
$ bash selecciona.sh
1) beans
2) carrots
3) potatoes
4) onions
5) rutabagas
Choose your favorite vegetable: 2

Your favorite veggie is carrots!

Un altre exemple, escollir algun dels fitxers del directori de treball:

select fname in *;
 do
  echo you picked $fname \($REPLY\)
  break;
 done

bucles

for

La sintaxi és:

 for name [in words ...]; 
  do 
   commands ; 
  done

Per exemple:

 $ for i in 1 2 3 4 5; do echo "Welcome $i times" ; done
 Welcome 1 times
 Welcome 2 times
 Welcome 3 times
 Welcome 4 times
 Welcome 5 times

També podeu utilitzar una variable:

FRUITS="apple pineapple watermelon lemon"
for fruit in $FRUITS; 
 do 
   echo $fruit
 done

Per fer un for a l'estil de C:

 for (( expr1 ; expr2 ; expr3 )) ;
  do
   commands ;
  done

Un exemple:

for (( c=1; c<=5; c++ )); 
 do 
  echo "Welcome $c times..."; 
 done

Paràmetres posicionals

"in words" és opcional per què si no l'especifiqueu s'iteren els paràmetres posicionals:

$ joe for_pp.sh
for positional_parameter;
 do
   echo $positional_parameter;
 done
$ bash for_pp.sh 1 2 3 4
1
2
3
4

De fet és equivalent a:

for positional_parameter in "$@";
 do
   echo $positional_parameter;
 done

El codi de retorn és el de l'última ordre executada.

Un sintaxi alternativa és (més similar a les utilitzades en llenguatges de programació com C, PHP o Java):

for (( expr1 ; expr2 ; expr3 )) ; 
 do 
  commands ; 
done

Per exemple:

#!/bin/bash
for (( c=1; c<=5; c++ ))
do 
	echo "Welcome $c times..."
done

o

$ for (( c=1; c<=5; c++ )); do echo "Welcome $c times...";  done
Welcome 1 times...
Welcome 2 times...
Welcome 3 times...
Welcome 4 times...
Welcome 5 times...

Per fer un bucle infinit:

#!/bin/bash
for (( ; ; ))
do
   echo "infinite loops [ hit CTRL+C to stop]"
done

Es pot trencar el bucle en qualsevol moment amb l'ordre break:

for I in 1 2 3 4 5
do
  statements1      #Executed for all values of I, up to a disaster-condition if any.
  statements2
  if (disaster-condition)
  then 
	break       	   #Abandon the loop.
  fi
  statements3          #While good and, no disaster-condition.
done 

O continuar cap a la següent iteració abans de temps amb continue:

for I in 1 2 3 4 5
do
  statements1      #Executed for all values of I, up to a disaster-condition if any.
  statements2
  if (condition)
  then 
	continue   #Go to next iteration of I in the loop and skip statements3
  fi
  statements3
done
while

La sintaxi d'aquesta construcció és:

while test-commands ; 
 do 
  consequent-commands ; 
 done

El que fa és executar la llista d'ordres consequent-commands mentrestant l'execució de les test-commands retorni un valor igual a zero.

Un exemple:

#!/bin/bash 
COUNTER=0
while [  $COUNTER -lt 10 ]; 
 do
   echo The counter is $COUNTER
   let COUNTER=COUNTER+1 
 done

Un altre exemple clàssic és el càlcul del factorial d'un número:

#!/bin/bash
counter=$1
factorial=1
while [ $counter -gt 0 ]
do
   factorial=$(( $factorial * $counter ))
   counter=$(( $counter - 1 ))
done
echo $factorial

Per provar-lo:

$ chmod +x factorial.sh
$ ./factorial.sh 5

Un altre exemple bastant habitual és el d'iterar un fitxer línia a línia:

#!/bin/bash

cat filename | while read line; do
  echo $line
done
until

La sintaxi de l'ordre és:

until test-commands ; 
 do 
  consequent-commands ; 
 done

Executa:

consequent-commands

Mentrestant les:

test-commands

tinguin un codi de retorn diferent de zero.

Vegem un exemple:

#!/bin/bash 
COUNTER=20
until [  $COUNTER -lt 10 ]; 
 do
   echo COUNTER $COUNTER
   let COUNTER-=1
 done

includes

Per fer un inclusió d'un fitxer podeu utilitzar:

. /lib/lsb/init-functions

O també l'ordre source

source /lib/lsb/init-functions

Pot ser interessant només fer la inclusió si el fitxer existeix:

test -f /etc/default/rcS && . /etc/default/rcS

o:

if [ -f /etc/default/apache2 ] ; then
	. /etc/default/apache2
fi

Vegeu també include

Substitució d'ordres

La substitució d'ordre permet que la sortida d'un ordre reemplaci a la pròpia ordre. Això succeïx quan s'utilitza:

$(ordre)            RECOMANAT

o

`ordre`

Bash realitza la expansió executant l'ordre i reemplaçant la substitució de l'ordre per la sortida estàndard de l'ordre.

Vegem un exemple:

$ date=$(date)
$ echo $date
dl mar 8 17:29:11 CET 2010

Un altre exemple:

script_name=`basename $0`
echo "The name of this script is $script_name."

Cal tenir en compte que es poden arribar a eliminar els salts de línia. Proveu:

$ dir_listing=`ls -l`
$ echo $dir_listing

En canvi (quoting):

$ echo "$dir_listing" 

Us donarà el resultat esperat.

Espais en blanc (whitespace). Internal Field Separator ($IFS)

Cal tenir en compte que a bash quan es parla d'un espai en blanc es fa referència a quatre opcions:

espai en blanc
tabulador
nova línia
qualsevol combinació de les anteriors de forma consecutiva 

Bash utilitza el que s'anomena separació de paraules (word splitting) en múltiples ocasions (p. ex. amb l'ordre interna read). Es consideren paraules aquelles que estan delimitades per un espai en blanc (és a dir una de les 3 opcions indicades anteriorment!)

El caràcter especial $IFS determina quin és el separador de paraula.

Per veure'l correctament cal fer:

$ echo "$IFS" | cat -vte
 ^I$
$

On podeu veure l'espai a la primera línia, després es mostra el tabulador (^I) i finalment el salt de línia (els $ indicant on s'acaben les línies)

Vegem un exemple de modificació de bash:

$ joe split.sh
data='x|y|z'
IFS='|'
for i in $data
 do
  echo $i
 done
$ bash split.sh
x
y
z

Vegeu també un exemple:

Exemples_de_Shell_Scripts#Iterar_un_fitxer_l.C3.ADnia_a_l.C3.ADnia

De com es pot utilitzar el IFS per iterar un fitxer línia a línia.


Tingueu en compte que per canviar el valor de IFS cal utilitzar l'apostrof o comillar simple:

#!/bin/bash
IFS=$','
vals='/mnt,/var/lib/vmware/Virtual Machines,/dev,/proc,/sys,/tmp,/usr/portage,/var/tmp'
for i in $vals; do echo $i; done
unset IFS

La sortida serà:

/mnt
/var/lib/vmware/Virtual Machines
/dev
/proc
/sys
/tmp
/usr/portage
/var/tmp

IMPORTANT: Tingueu en compte que la variable IFS és utilitzada per múltiples ordres i/o aplicacions. Es recomanable que la torneu al seu valor per defecte amb unset, tal i com es fa a l'exemple

Recursos:

heredocs

Consulteu heredoc.

Seqüències. Ordre seq

Permet crear una seqüència de nombres enters.

$ seq 5
1
2
3
4
5

El separador pe defecte és nova línia (es pot canviar amb -s):

$ seq -s : 5
1:2:3:4:5

S'utilitza per fer bucles:

COUNT=80  
#COUNT=$1
for a in $(seq $COUNT)
 do
  echo -n "$a "
 done

Un altre exemple:

$ for I in $(seq 1 10); do echo $I; done

yes

Proveu:

$ yes
y
y
y
...

Es pot utilitzar (en compte!) per contestar les típiques preguntes: segur que vols continuar (y/n)?

$ yes | rm -r dirname 

run-parts

Executa tots els guions d'un directori:

$ run-parts directori_amb_guions

L'ordre és alfabètic. Es poden posar números davant dels scripts per controlar en quin ordre s'executen.

IMPORTANT: En algunes distribucions si els scripts contenen el caràcter punt (.), és a dir tenen una extensió, aleshores no s'executen. De fet el manual de Debian comenta que només poden tenir caràcters,números o guions baixos (_) o guions (-)

Del manual:

$ man run-parts
If  neither  the  --lsbsysinit option nor the
      --regex option is given then the  names  must
      consist entirely of upper and lower case let‐
      ters, digits, underscores, and hyphens.

script

La sintaxi segons el manual és:

$ man script
... 
script [-a] [-c COMMAND] [-f] [-q] [-t] [file

Aquesta ordre un cop iniciada guarda en un fitxer tot el que s'executa a la terminal. És útil per tal que els alumnes puguin guardar una còpia de les tasques que realitzen a la terminal segons uns deures que se'ls ha demanat.

Abans de començar cal executar script (iniciar una sessió). Teniu dos opcions:

$ script

o

$ script sessio.txt

Si no especifiqueu cap fitxer la sessió es guarda al fitxer typescript.

Feu una prova:

$ script sessio.txt
S'ha iniciat l'execució de script, el fitxer és sessio.txt
$ ls
$ echo "prova"

Per finalitzar una sessió cal prémer la combinació de tecles:

Ctrl+D
S'ha fet la seqüència, el fitxer és sessio.txt

Ara podeu consultar el fitxer:

$ cat sessio.txt 
S'ha iniciat l'execució de script a dt 09 mar 2010 11:44:36 CET 
sergi@BSFHPCasa:~$ ls
< resultat del ls >
sergi@BSFHPCasa:~$ echo "Prova"
Prova
sergi@BSFHPCasa:~$ exit
S'ha finalitzat l'execució de script a dt 09 mar 2010 11:44:57 CET

El fitxer es pot anar creant a l'estil d'un fitxer de log (-f following) i es pot reaprofitar un fitxer (-a append):

$ script -f -a sessio.txt

Des d'un altre terminal o d'un altre usuari (o una sessió remota) podeu executar:

$ tail -f sessio.txt

En comptes d'executar una terminal interactiva es pot executar un ordre o guió de shell amb:

-c COMMAND

Pot ser molt útil per capturar la sortida d'un programa que no envia la sortida per la terminals estàndard d'error.

NOTA: Script no funciona gaire bé amb ordres com vi que manipulen directamen la pantalla.

Obtenir informació de l'entrada de la línia d'ordres. read

L'ordre interna read permet capturar dades de l'entrada estàndard. Segons el manual de bash la sintaxi és:

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-p prompt] [-t timeout] [-u fd] [name ...]

El que fa read és llegir una línia de l'entrada estàndard. Amb l'opció -u es pot obtenir les dades d'un descriptor de fitxer (en comptes de l'entrada estàndard).

La forma més bàsica d'utilitzar read és:

$ read
Hola Mon!
$ echo $REPLY
Hola Mon!

La variable REPLY conté el text introduït a la entrada estàndard. Podem guardar la línia en una nova variable amb:

$ read HOLA
Hola Sergi!
$ echo $REPLY
Hola Mon!
$ echo $HOLA
Hola Sergi!

Es poden llegir múltiples valors d'un sol cop amb:

$ joe hola.sh
#!/bin/bash
echo "Si us plau introdueix el teu nom i cognoms:"
read NOM COGNOMS 
echo "Hola $COGNOMS, $NOM !"

Per provar-lo:

$ bash hola.sh 
Si us plau introdueix el teu nom i cognoms:
Sergi Tur Badenas
Hola Tur Badenas, Sergi!

El que fa realment es dividir l'entrada en paraules (separades per espais). Com que només especifiquem 2 variables i nosaltres especifiquem 2 paraules (nom + 2 cognoms) la segona variable conté tot el text fins al final de línia. És dir el guió és equivalent a:

#!/bin/bash
echo "Si us plau introdueix el teu nom i cognoms:"
read NOM COGNOM1 COGNOM2
echo "Hola $COGNOM1 $COGNOM2, $NOM !"

NOTA: El caràcter IFS és utilitzar per separar la línia en paraules (per defecte és l'espai)

També s'utilitza per iterar un fitxer línia a línia amb:

#!/bin/bash

cat filename | while read line; do
  echo $line
done

També es pot guardar les paraules en un array:

$ joe quedarbe.sh
echo "Quins són els teus colors preferits?"
read -a colors
echo "Els meus colors favorits també són: " 
for i in "${colors[@]}"
 do
  echo $i
 done
echo ";-)"

També es pot indicar un PROMPT:

$ read -p numero:
numero:1
$ echo $REPLY
1

Altres opcions són:

  • -d delim: Especificar quin paràmetres s'utilitza per determinar que és una nova línia
  • -n nchars: read acaba un cop ha llegti n caràcters.
  • -t timeout: especificar un temps màxim d'espera d'una entrada.

Preguntar una paraula de pas

 #!/bin/bash
 read -p "Username: " uname
 [[stty]] -echo
 read -p "Password: " passw; echo
 stty echo

Preguntar si esteu segurs

asksure() {
echo -n "Are you sure (Y/N)? "
while read -r -n 1 -s answer; do
  if [[ $answer = [YyNn] ]]; then
    [[ $answer = [Yy] ]] && retval=0
    [[ $answer = [Nn] ]] && retval=1
    break
  fi
done    

echo # just a final linefeed, optics... 

return $retval
}

### using it
if asksure; then
  echo "Okay, performing rm -rf / then, master...."
else
  echo "Pfff..."
fi

Funcions bash

El següent és un exemple senzill de com declarar funcions en bash i com utilitzar-les:

 #!/bin/bash 
           function quit {
               exit
           }
           function hello {
               echo Hello!
           }
           hello
           quit
           echo foo 


Depurar

Es pot veure el codi font i executar un guió de shell amb:

$ bash -v script.sh

O es pot establir:

set -v

al principi del guió.

Per tal de veure les expressions avaluades mentrestant el guió s'executa:

$ bash -x script.sh

O es pot establir:

set -x

al principi del guió.

També són útils les opcions (quan s'està en fase de depuració):

$ set –o xtrace
$ set –o nounset

Així serà més fàcil rastrejar l’execució del programa i s’evitarà cridar en el codi variables sense inicialitzar.

$LINENO

Conté el número de línia de l’script del shell on apareix. Només té sentit dins de l’script on apareix i s’utilitza especialment a la fase de depuració. Vegem un exemple:

$ joe test.sh
#!/bin/bash

#Comentari
echo "Aquesta és la línia: $LINENO"

echo "Un altre línia: nº: $LINENO"

Si ara l'executeu:

$ bash test.sh 
Aquesta és la línia: 4
Un altre línia: nº: 6

traps

Exemple de com capturar el ctrl+c

#!/bin/bash
# bash trap command
trap bashtrap STOP
# bash clear screen command
clear;
# bash trap function is executed when CTRL-C is pressed:
# bash prints message => Executing bash trap subrutine !
bashtrap()
{
    echo "CTRL+C Detected !...executing bash trap !"
    read -p "Press Enter to continue"
}

# for loop from 1/10 to 10/10
 for a in `seq 1 100 `; do
  echo "$a/10 to Exit." 
  sleep 1;
 done
echo "Exit Bash Trap Example!!!" 

Enviar correus condicionals al superusuari

Consulteu l'ordre mail.

Exemples

Troubleshooting. Resol·lució de problemes

Variables que es reinicien després d'un loop (while,for) on-empty variable before loop end, is empty after exiting loop

Error:

/bin/cat $USERS_FILE | while read line; do
	USERNAME=$(/bin/echo $line | /usr/bin/cut -d ";" -f1)
	FULLNAME=$(/bin/echo $line | /usr/bin/cut -d ";" -f2)
	HASH=$(/bin/echo $line | /usr/bin/cut -d ";" -f3)
	
        echo "Creating user: $USERNAME..."
    
        /usr/sbin/groupadd $USERNAME
	/usr/sbin/useradd -m -s /bin/bash -g $USERNAME -G $GROUPS -c "$FULLNAME" $USERNAME	
done

{{important|La variable $GROUPS està definida fora del loop i no tindrà el valor que li pertoca!}}

'''Ok''':
<pre class="brush:bash">while read line; do
	USERNAME=$(/bin/echo $line | /usr/bin/cut -d ";" -f1)
	FULLNAME=$(/bin/echo $line | /usr/bin/cut -d ";" -f2)
	HASH=$(/bin/echo $line | /usr/bin/cut -d ";" -f3)
	
        echo "Creating user: $USERNAME..."
    
        /usr/sbin/groupadd $USERNAME
	/usr/sbin/useradd -m -s /bin/bash -g $USERNAME -G $GROUPS -c "$FULLNAME" $USERNAME	
done <<< "$(/bin/cat $USERS_FILE)"

Vegeu també