Scripts en Linux (Bash).
Què són els scripts dels SO?
Section titled “Què són els scripts dels SO?”Els intèrprets d’ordres o shells són programes que permeten la interacció dels usuaris amb el S.O. i el seu hardware. També incorporen llenguatges de programació per a crear programari que anomenem scripts
(en català, guions
).
Els scripts de shell són molt útils per fer tasques de gestió i administració del sistema (com monitoritzar les tasques en execució) i altres treballs repetitius que no requereixen un llenguatge de programació més sofisticat (per exemple, còpies de seguretat)
Intèrprets d’ordres a Windows
Section titled “Intèrprets d’ordres a Windows”Command Prompt (cmd.exe): Aquest és l’intèrpret d’ordres clàssic de Windows. Equivalent i compatible al COMMAND.COM d’MS-DOS i versions de Windows de 16 i 32 bits. Té dos modes d’execució:
- Interactiu: l’usuari escriu les ordres per ser executades
- Mode per lots (batch): executa una sentència predefinida d’ordres guardada en un .bat
Windows PowerShell: interfície de consola per a S.O. Windows llançada el 2006, incorporat des de Windows 7, que té com a utilitat principal l’automatització de tasques administratives més avançades. Té una sintaxi més moderna, basada en la programació orientada a objectes.
Els 2 intèrprets coexisteixen i s’utilitzen per propòsits diferents.
Intèrprets d’ordres a Linux
Section titled “Intèrprets d’ordres a Linux”El shell Bash (Bourne-Again Shell) és l’intèrpret d’ordres predeterminat de gairebé totes les distribucions GNU/Linux, així com de Mac OS X, i pot executar-se en la majoria dels sistemes operatius tipus Unix.
Se’n poden instal·lar d’altres a Linux, com Zsh que incorpora algunes funcionalitats més avançades i més personalització.
Intèrprets d’ordres a Mac
Section titled “Intèrprets d’ordres a Mac”Tant macOS (originalment OS X) com Linux tenen les seves arrels en Unix
, un sistema operatiu desenvolupat als anys 70 amb llicència BSD () i àmpliament utilitzat per implantar sistemes operatius multiusuari els anys 80. Aquesta herència comuna ha fet que molts components i idees siguin compartides entre ambdós sistemes operatius, incloent-hi els shells.
Quan Apple va llançar OS X (ara macOS) el 2001, es va basar en un nucli Unix BSD i va triar Bash (Bourne Again Shell) com a shell predeterminat per la seva popularitat i compatibilitat amb scripts existents.
Un dels dubtes més freqüents quan s’estudien les llicències dels SO és com pot ser que Mac i Linux, que tenen un enfocament totalment oposat respecte les llibertats del usuaris, poden compartir els mateixos intèrprets d’ordres, part del programari i la arquitectura.
Apple va poder utilitzar components del sistema operatiu BSD (Berkeley Software Distribution), una variant d’Unix desenvolupada a la Universitat de Califòrnia, Berkeley. BSD té una llicència més permissiva que la GPL (General Public License) de Linux, que permet l’ús i la distribució de codi modificat amb menys restriccions. És a dir, que permet llicenciar el programari derivat amb una llicència propietària d’Apple.
Com executar un script a Linux ?
Section titled “Com executar un script a Linux ?”Abans de començar a entendre la sintaxi del llenguatge d’scripts de Bash. El que farem és crear un nou script, a partir d’un fitxer amb instruccions, li donarem els permisos per a que sigui executable i finalment l’executarem.
Per a crear el teu script amb la shell de Linux obre el terminal (cerca el programa que té una pantalla negre com a icona , o usa la drecera Ctrl+Alt+T)
- Crea el fitxer
hacking.sh
amb un editor com nano o gedit, amb extensió sh.
#!/bin/bashfor i in {1..100}do echo "Hacking. $i% completed." sleep 2doneecho "Hacking completed :)"
- Converteix-lo a programa, assignant permisos d’execució.
chmod u+x hacking.shls -l
- Executa i a gaudir :)
./hacking.sh
Resultat esperat: Cada 2 segons sortirà el mateix missatge, a excepció del número % completed, que gràcies al bucle s’anirà incrementant.
Hacking. 1% completed.Hacking. 2% completed.Hacking. 3% completed.
Una alternativa als passos 2 i 3, si no ets un usuari amb permisos d’administrador (no estàs al grup sudo), és aquesta:
sh hacking.sh
Variables locals i variables d’entorn
Section titled “Variables locals i variables d’entorn”Al shell, una variable és un nom que representa un valor que volem guardar pel seu posterior ús en un o més punts dels nostres programes.
Poden ser:
- Locals: només són visibles pel shell en el qual estem treballant, no són visibles per cap shell fill.
Per a declarar variables és important recordar que:
- Les variables d’entorn no poden tindre espais, i si volem assignar un valor amb espai hem de “entrecomillar”, o bé precedir l’espai per un
caràcter d’escapament
. - Per mostrar la variable mitjançant la funció
echo
l’hem de precedir amb el símbol de dòlar$
.
NOM='Katy Perry'echo $NOM
Katy Perry
NOM=Katy\ Perryecho $NOM
Katy Perry
Per a eliminar una variable d’entorn podem usar la comanda unset
.
Per exemple:
unset $NOMecho $NOM
D’aquesta manera podrem fer inteccacions com les següents:
variable1='Sabates negres'variable2=20.5echo "L’article $variable1 costa $variable2 euros"
L’article Sabates negres costa 20.5 euros
- D’entorn: són visibles tant pel shell pare com pels shells fills. Per defecte disposem de variables d’entorn predefinides que ens poden resultar útils per a la programació d’scripts.
export NOM_VAR = valor
Hi ha diverses ordres relacionades amb les variables:
Ordre set Permet veure totes les variables (locals i d’entorn) definides en una sessió.
Ordre env Permet veure les variables d’entorn definides en una sessió.
Exemples típics:
- USER: Nom de l’usuari actiu
- HOME: Directori de l’usuari (per defecte /home/USER )
- PWD: Directori on es troba l’usuari
- PATH: Llista de directoris on cercar programes abans de buscar-los al disc. Permet executar un programa sense dir-li la ruta sencera.
Si volem veure el valor d’una variable en concret; la instrucció és igual que si fos una de local.
echo $PWD
Possible resultat:
/home/mamoros/Documents/
Si volem guardar totes les variables d’entorn en un fitxer usem l’operador de redirecció >
:
echo env > vars_ent.txt
{% image “linux-venvs.png” %}
Caràcters especials.
Section titled “Caràcters especials.”Hi ha caràcters que per a la shell tenen un significat especial. Existeixen diferents tècniques per tal que la shell ignori aquest significat o el tingui en compte:
**** anul·la el significat especial del caràcter que va darrera
‘’ anul·la el significat especial de tots els caràcters que estiguin dins les cometes
“” anul·la el significat especial de tots els caràcters excepte: $ \ “ “”
Exemple: echo “Això és \”una prova\””
Exemple: echo “Sóc el/la $LOGNAME i estic a $PWD: $PWD”
Tractament de la data del sistema.
Section titled “Tractament de la data del sistema.”Saber la data i hora del sistema en funció de la nostra zona horària és molt important per a certes tasques: monitoritzar la activitat d’un ordinador servidor, posar nom i data de les còpies de seguretat…
Per mostrar la data del sistema en format llarg ho podem fer cridant la funció del sistema date; fixa’t que per a què es mostri el resultat de la funció l’hem de rodejar entre parèntesis i un símbol de dòlar: $(date)
echo “La data del sistema és: $(date)”
Si volem un format més curt i propi de la nostra zona (que es mostri en format dd/mm/aaaa i la hora per separat) ho podem fer assignant el format que volem com a paràmetre.
data=$(date +%d/%m/%Y)hora=$(date +%H:%M:%S)echo "Data en format ddmmaaaa: $data"echo "Hora en format hh:mm:ss: $hora"
Data en format ddmmaaaa: 06/08/2024 Hora en format hh:mm:ss: 22:40:33
En ocasions el sistema no detectarà automàticament el nostre fus horari (això passa en màquines virtuals sobretot) i si és el cas el podrem consultar i editar:
timedatectl
sudo timedatectl set-timezone Europe/Madrid
Recurs ampliació.
[https://learning.lpi.org/es/learning-materials/102-500/108/108.1/](Certificació Linux LPI 102, zones horàries)
Exercici 1. Crea un script que crei una carpeta dins del directori actual (on et trobes) amb el nom projecte-<data_avui>-<hora_avui> i al final informi de la seva creació correcta. Recorda que pots usar instruccions com mkdir i cd.
Observació Per ara no farem el tractament de què fer si existeix una carpeta igual (ja el farem un cop vists els condicionals)
{% sol %}
ex1-scr.sh
data=$(date +%d/%m/%Y)hora=$(date +%H:%M)carpeta="projecte-${data}-${hora}"mkdir $carpetaecho "Carpeta del projecte $carpeta creada correctament"
Possible resultat execució:
$ nano ex1-scr.sh$ chmod u+x ex1-scr.sh$ ./ex1-scr.shCarpeta del projecte projecte-18/02/2025-22:48 creada correctament
{% endsol %}
Pas de paràmetres.
Section titled “Pas de paràmetres.”Un script és un fitxer que conté comandos Bash executables. Els fitxers ocults de configuració de Bash com .bash_profile o .bashrc, vistos en la part de la gestió d’usuari són exemples de scripts.
Principalment Bash utilitza variables de tipus cadena de caràcters. Això li diferencia d’altres llenguatges de programació on les variables poden tenir diferents tipus predefinits. Encara que aquest és el tipus per defecte de les variables de Bash, més endavant veurem que les variables en Bash també poden tindre altres tipus, com per exemple números amb els quals realitzar operacions aritmètiques; tal i com passa amb els llenguatges de tipat dinàmic com Python o Javascript.
Per conveni les variables d’entorn exportades (les que passem als subprocesos) s’escriuen en majúscules, i les que no exportem en minúscules.
Aquesta regla, més que per la manera interactiva, és especialment seguida pels scripts i funcions que començarem a programar ara.
Els paràmetres posicionals són els encarregats de rebre els arguments d’un script i els paràmetres d’una funció.
Els seus noms són 1, 2, 3, etc., amb el que per a accedir a ells utilitzarem, com normalment, el símbol $
de la forma $1
, $2
, $3
, etc.
A més tenim el paràmetre posicional 0 ($0
) que emmagatzema el nom del script on s’executa.
#!/bin/bash#Exemple de script que rep paràmetres y les imprimeixecho "El script $0"echo "Rep els arguments $1 $2 $3 $4"
Si ho hem guardat en un fitxer anomenat rep amb el permís d’execució activat podem executar-lo així:
chmod u+x rep./rep hola adios
Resultat:
El script ./repRep els arguments hola adios
Codis de terminació.
Section titled “Codis de terminació.”En UNIX les comandes acaben retornant un codi numèric al qual es diu codi de terminació (exit estatus) que indica si el comando va tindre èxit o no.
Encara que no és obligatori que siga així, normalment un codi de terminació 0 significa que el comando va acabar correctament, i un codi entre 1 i 255 correspon a possibles codis d’error.
Per a llegir el codi de terminació de l’últim comando executat disposem de la variable ?, el valor del qual és $?.
Per exemple:
$ cd direrroneo-bash: cd: direrroneo: No such file or directory$ echo $?
1
La variable ?
ha de ser llegida junt després d’executar la comandes, doncs és molt típic guardar el seu valor en una variable ct=$?
per al seu posterior ús.
Condicions: if, elif, else
Section titled “Condicions: if, elif, else”La sentència condicional if
permet executar diferents ordres en funció d’una condició.
En Bash, la seva estructura bàsica és:
if condiciothen # Sentències si la condició és certaelif condiciothen # Sentències si la segona condició és certaelse # Sentències si cap condició anterior és certafi
Exemple: Pregunta a l’usuari un número i comprova si un número és positiu, negatiu o 0.
#!/bin/bash
echo "Introdueix un número:"read num
if [[ $num -gt 0 ]]then echo "El número és positiu."elif [[ $num -lt 0 ]]then echo "El número és negatiu."else echo "El número és zero."fi
Lectura de fitxers.
Section titled “Lectura de fitxers.”Ara veurem com llegir un fitxer que tinguem al disc dur. Comprovarem que sigui un fitxer vàlid.
Creem un fitxer de prova amb el nano o l’editor que volgueu:
prova.csv
nom,edat,ciutatJoan,25,BarcelonaAnna,30,GironaMarc,22,TarragonaFanny,21,Barcelona
Per llegir-lo, en cas que existeixi, ho fem així:
#!/bin/bashif [[ -f prova.csv ]]then cat prova.csvelse echo "El fitxer prova.csv no existeix!"fi
El paràmetre -f
verifica que prova.csv sigui un fitxer vàlid.
La comanda cat
mostra tot el contingut del fitxer.
Si necessites una solució més robusta, per a qualsevol fitxer passat per paràmetre:
#!/bin/bash
# Comprovar si s'ha passat un fitxerif [[ $# -ne 1 ]]; then echo "Ús: $0 prova.csv" exit 1fi
fitxer="$1"
# Comprovar si el fitxer existeixif [[ ! -f "$fitxer" ]]; then echo "Error: El fitxer '$fitxer' no existeix." exit 1fi
# Mostrar el contingut del CSV (sense la capçalera)cat "$fitxer"
Exemple lectura/escriptura de fitxers i directoris.
Section titled “Exemple lectura/escriptura de fitxers i directoris.”En moltes ocasions necessitem crear una estructura de directoris per a projectes.
Per exemple; crear un script al qual li passis el nom d’un projecte.
Si no existeix una carpeta amb el nom de projecte crearà: a. La carpeta amb el nom del projecte b. Les subcarpetes: css, img, js, static. c. Un fitxer anomenat readme.md que contingui: i. A la primera línia «#Documentació del projecte» ii. A la segona línia la **data d’avui.v iii. La tercera línia el nom de l’usuari.
Si el nom de la carpeta existeix mostrarà un missatge d’avís i no la crearà.
ExCreaprojecte.sh
#!/bin/bashif [ ! -d $1 ] then echo "Creem projecte web amb el nom " $1 mkdir $1 cd $1 echo "Creem carpetes " mkdir {css,img,js,static} echo "Creem fitxer descriptor" touch readme.md echo "#Documentació del projecte" >> readme.md NOW=$(date +"%d-%m-%Y") echo "Data creació: $NOW" >> readme.md echo "Creat per: $USERNAME" >> readme.md cd .. echo "Projecte $1 creat correctament."else if [ $# -eq 0 ] then echo "Has d'introduir el nom del projecte web que vols crear." echo "$0 prj-demo" else echo "La carpeta del projecte $1 ja existeix." fifi
En aquest script hem posat a prova tot el que hem après anteriorment.
Provem les 3 casuïstiques:
- Què passa si no li passem cap carpeta
- Si li passem carpeta que no existeix (crea el projecte)
- Si li passem carpeta que existeix.
isard@ubuntu:~/Baixades/Solucions_Scripts$ ./ExCreaprojecte.shHas d'introduir el nom del projecte web que vols crear.
isard@ubuntu:~/Baixades/Solucions_Scripts$ ./ExCreaprojecte.sh prj-demo
isard@ubuntu:~/Baixades/Solucions_Scripts$ ./ExCreaprojecte.sh dawbio1Creem projecte web amb el nom dawbio1Creem carpetesCreem fitxer descriptorProjecte dawbio1 creat correctament.
isard@ubuntu:~/Baixades/Solucions_Scripts$ ls dawbio1/css img js readme.md static
isard@ubuntu:~/Baixades/Solucions_Scripts$ cat dawbio1/readme.md#Documentació del projecteData creació: 28-02-2024Creat per: isard
isard@ubuntu:~/Baixades/Solucions_Scripts$ ./ExCreaprojecte.sh dawbio1La carpeta del projecte dawbio1 ja existeix.
Sintaxi comparadors i comprovació atributs de fitxers.
Section titled “Sintaxi comparadors i comprovació atributs de fitxers.”Revisa aquest article per aprendre tots els possibles comparadors de condicions, com -gt
. O verificadors d’atributs de fitxers com -f
.
-https://atareao.es/tutorial/scripts-en-bash/condicionales-en-bash/
Instal·lació programari necessari.
Section titled “Instal·lació programari necessari.”En ocasions per a què un programa funcioni necessitem que l’equip de l’usuari tingui instal·lat algún programa que no ve preinstal·lat a la seva distribució.
Per exemple, per mostrar els directoris en forma d’arbre necessitarà el tree
, o per baixar-se un fitxer d’Internet el curl
.
Per estalviar-li feina, podem instal·lar-lo automàticament en cas que no el tingui:
#!/bin/bashif ! command -v curl &>/dev/null; then sudo apt update && sudo apt install -y curlfi
curl -L -O https://upload.wikimedia.org/wikipedia/commons/e/ee/GNU%2BLinux.png
Ja hauries de tenir el programa curl
i la imatge .png
descarregada.
Pot ser que consideris que forçar a l’usuari executar scripts que forcin la instal·lació de programari sigui invasiu, però aquesta és una pràctica molt habitual, per exemple per a desenvolupadors, que volen centrar-se que la seva web funcioni sense preocupar-se gaire en aspectes del sistema operatiu.
Per exemple gestors de llibreries Javascript com nvm
o bun
.
Programari distribucions diferents a les basades en Debian/Ubuntu
Section titled “Programari distribucions diferents a les basades en Debian/Ubuntu”Si volem portar l’script en una distribució diferent a les que hem vist com és el cas de Fedora o Redhat totes les comandes haurien de ser igual excepte el bloc de l’apt.
Aquí tenim una mostra del que hauriem de fer per a què el nostre script també funcioni en aquestes distribucions, que també són populars.
echo "⚠️ Curl no està instal·lat. Intentant instal·lar-lo..." if command -v apt &>/dev/null; then sudo apt update && sudo apt install -y curl elif command -v dnf &>/dev/null; then sudo dnf install -y curl else echo "❌ No es pot instal·lar curl automàticament. Instal·la'l manualment." exit 1 fi
Comprovació que un fitxer ja ha estat descarregat.
Section titled “Comprovació que un fitxer ja ha estat descarregat.”Si volem crear un programa que llegeixi informació d’algun fitxer amb molta informació i aquest ja l’hem descarregat prèviament, per estalviar temps i un accés innecessari a Internet (que gasta electricitat) ens anirà molt bé usar un condicional per a què:
Cas 1.1 En el cas que el fitxer no el tinguem al disc el descarregui.
Cas 1.2 Si el fitxer ja l’hem descarregat abans (ho podem saber pel nom) no el descarregui.
Cas 2 En qualsevol dels 2 casos hauria de mostrar a l’usuari la informació del fitxer.
Exemple pràctic.
Volem crear un programa que descarregui una seqüència d’Uniprot passada per paràmetre i mostri per pantalla el seu contingut (el format d’aquestes comença per P, per exemple P12345) i es baixaran en format .fasta
Si ja s’ha descarregat abans no cal que ho faci.
Si l’usuari no envia cap identificador el programa avisarà un text com aquest: ”❌ Ús: $0 <UniProt_ID>” i es tancarà.
La URL on es pot descarregar qualsevol proteïna pel seu UNIPROT_ID té la següent forma:
URL="https://rest.uniprot.org/uniprotkb/${UNIPROT_ID}.fasta"
Aquí tenim una solució completa a aquest problema:
#!/bin/bash
# Comprova si s'ha proporcionat un IDif [ -z "$1" ]; then echo "❌ Ús: $0 <UniProt_ID>" exit 1fi
# Instal·la el curl per baixar la proteïna si l'usuari del SO no el té.if ! command -v curl &>/dev/null; then sudo apt update && sudo apt install -y curlfi
# Identificador de la proteïnaUNIPROT_ID="$1"
# Nom del fitxer de sortidaOUTPUT_FILE="${UNIPROT_ID}.fasta"
# URL d'UniProt per descarregar en format FASTAURL="https://rest.uniprot.org/uniprotkb/${UNIPROT_ID}.fasta"
# Comprovar si el fitxer ja existeixif [ -f "$OUTPUT_FILE" ]; then echo "ℹ️ El fitxer $OUTPUT_FILE ja existeix. No es farà la descàrrega."else echo "📥 Descarregant la proteïna $UNIPROT_ID en format FASTA..." curl -L -s -o "$OUTPUT_FILE" "$URL"
# Comprovar si la descàrrega ha estat exitosa if [ ! -s "$OUTPUT_FILE" ]; then echo "❌ Error en descarregar la proteïna. Comprova l'ID proporcionat." rm -f "$OUTPUT_FILE" # Esborra el fitxer buit si la descàrrega ha fallat exit 1 fi echo "✅ Descarrega completada! Fitxer guardat com: $OUTPUT_FILE"fi
# Mostrar el contingut del fitxerecho "📄 Contingut de $OUTPUT_FILE:"cat "$OUTPUT_FILE"
I els resultats que evidencien que funciona:
✅ Descarrega completada! Fitxer guardat com: P12345.fasta📄 Contingut de P12345.fasta:>sp|P12345|AATM_RABIT Aspartate aminotransferase, mitochondrial OS=Oryctolagus cuniculus OX=9986 GN=GOT2 PE=1 SV=2MALLHSARVLSGVASAFHPGLAAAASARASSWWAHVEMGPPDPILGVTEAYKRDTNSKKMNLGVGAYRDDNGKPYVLPSVRKAEAQIAAKGLDKEYLPIGGLAEFCRASAELALGENSEVVKSGRFVTVQTISGTGALRIGASFLQRFFKFSRDVFLPKPSWGNHTPIFRDAGMQLQSYRYYDPKTCGFDFTGALEDISKIPEQSVLLLHACAHNPTGVDPRPEQWKEIATVVKKRNLFAFFDMAYQGFASGDGDKDAWAVRHFIEQGINVCLCQSYAKNMGLYGERVGAFTVICKDADEAKRVESQLKILIRPMYSNPPIHGARIASTILTSPDLRKQWLQEVKGMADRIIGMRTQLVSNLKKEGSTHSWQHITDQIGMFCFTGLKPEQVERLTKEFSIYMTKDGRISVAGVTSGNVGYLAHAIHQVTKisard@ubuntu:~/prova$ ./uniprot.sh P12345ℹ️ El fitxer P12345.fasta ja existeix. No es farà la descàrrega.📄 Contingut de P12345.fasta:>sp|P12345|AATM_RABIT Aspartate aminotransferase, mitochondrial OS=Oryctolagus cuniculus OX=9986 GN=GOT2 PE=1 SV=2MALLHSARVLSGVASAFHPGLAAAASARASSWWAHVEMGPPDPILGVTEAYKRDTNSKKMNLGVGAYRDDNGKPYVLPSVRKAEAQIAAKGLDKEYLPIGGLAEFCRASAELALGENSEVVKSGRFVTVQTISGTGALRIGASFLQRFFKFSRDVFLPKPSWGNHTPIFRDAGMQLQSYRYYDPKTCGFDFTGALEDISKIPEQSVLLLHACAHNPTGVDPRPEQWKEIATVVKKRNLFAFFDMAYQGFASGDGDKDAWAVRHFIEQGINVCLCQSYAKNMGLYGERVGAFTVICKDADEAKRVESQLKILIRPMYSNPPIHGARIASTILTSPDLRKQWLQEVKGMADRIIGMRTQLVSNLKKEGSTHSWQHITDQIGMFCFTGLKPEQVERLTKEFSIYMTKDGRISVAGVTSGNVGYLAHAIHQVTK
2. Crea un script que realitzi una còpia de seguretat i comprimeixi tots els fitxers i directoris d’un directori passat per paràmetre per l’usuari (pex. /home/$USER/projecte ) sempre cap a la ruta destí /home/$USER/Documents.
El nom de la còpia ha de contenir el dia actual. Pots usar aquest codi per aconseguir-la:
NOW=$(date +"%d_%m_%Y")
{% sol %}
#!/bin/bash
# Comprovar si s'ha proporcionat el nom de la carpetaif [ $# -eq 0 ]; then echo "❌ Has d'introduir el nom de la carpeta on vols posar la còpia de seguretat." echo "🔹 Ús: $0 <nom_de_la_carpeta>" exit 1fi
# Carpeta on es vol fer la còpiaBACKUP_DIR="$1"
# Comprovar si la carpeta ja existeixif [ -d "$BACKUP_DIR" ]; then echo "ℹ️ La carpeta '$BACKUP_DIR' ja existeix. No es crearà una nova còpia." exit 0fi
# Generar nom de la còpia amb dataNOW=$(date +"%d_%m_%Y")BACKUP_NAME="${BACKUP_DIR}_${NOW}"
echo "📂 Creant còpia de seguretat amb el nom: ${BACKUP_NAME}.tar.gz"
# Crear còpia de seguretatSOURCE_FOLDER="/home/$USER/Documents/"tar -czvf "${BACKUP_NAME}.tar.gz" "$SOURCE_FOLDER"
# Comprovar si la còpia s'ha creat correctamentif [ $? -eq 0 ]; then echo "✅ Còpia de seguretat completada: ${BACKUP_NAME}.tar.gz"else echo "❌ Error en crear la còpia de seguretat!" exit 1fi
💡 Exemple d’ús
./backup.sh copia_segur
Si no passes cap argument:
❌ Has d'introduir el nom de la carpeta on vols posar la còpia de seguretat.🔹 Ús: ./backup.sh <nom_de_la_carpeta>
Si la carpeta ja existeix:
ℹ️ La carpeta 'copia_segur' ja existeix. No es crearà una nova còpia.
Si la còpia es fa correctament:
📂 Creant còpia de seguretat amb el nom: copia_segur_25_02_2025.tar.gz✅ Còpia de seguretat completada: copia_segur_25_02_2025.tar.gz
{% endsol %}
Bucles.
Section titled “Bucles.”Per a repetir la mateixa instrucció un número determinat de vegades usem els bucles.
Podem usar el bucle for
o el while
El bucle for en Bash és una mica diferent als bucles for tradicionals d’altres llenguatges com a C o Java, sinó que s’assembla més al bucle for each d’altres llenguatges com Python, ja que ací no es repeteix un nombre fix de vegades, sinó que es processen les paraules d’una frase una a una.
La seua sintaxi és la següent:
for var [in lista]do·····Sentencies que fan servir $var·····done
Un exemple d’aquest bucle l’hem vist al principi de tot; el fitxer hacking.sh
:
#!/bin/bashfor i in {1..100}do echo "Hacking. $i% completed." sleep 2doneecho "Hacking completed :)"
Un altre exemple senzill és aquest programa, que simula les tirades d’un dau. El nombre de vegades a tirar el dau se li ha de passar per teclat.
#!/bin/bashecho "Introdueix el nombre de vegades que vols llençar el dau"read vegades
for ((i=1;i<=$vegades;i++))do dau=$((1+$RANDOM % 6)) echo $i. $daudone
En canvi, un exemple del while
pot ser la lectura de fitxers amb la extensió fasta
:
#!/bin/bashfor i in *.fasta; do echo $i grep "^>" $idone
3. Crea un shell script que realitzi un sorteig entre els 13 nans de la novel·la The Hobbit per tal de saber qui s’enfrontarà al drac Smaug.
Disposarem del nom del 13 nans en un fitxer anomenat nans i amb el nom de cadascú a una línia diferent
nans.txt
ThorinBalinGlóinBifurBofurBomburDwalinOriDoriNoriÓinKíliFíli
Quan executem el script la sortida # haurà de ser del tipus:
S’ha d’enfrontar a Smaug: Nori
{% sol %}
Ex2Tolkien.sh
# Numero de nans dintre del fitxer `num_nans=`cat Nans.txt | wc -l`echo "Número de nans del sorteig = $num_nans"# num_nans = 13# Sorteig... Numero aleatorialeat=$(($RANDOM%$num_nans+1))echo "id de la persona petita $aleat"nan=`cat Nans.txt | head -$aleat | tail -1`echo "S'ha d'enfrontar a Smaug: $nan"
{% endsol %}
🖥️Funcions en Bash
Section titled “🖥️Funcions en Bash”Les funcions en Bash permeten modularitzar el codi i reutilitzar-lo fàcilment. A continuació, es mostren dos exemples:
🔹 Funció sense arguments
Section titled “🔹 Funció sense arguments”Aquesta funció mostra la data i l’hora actual.
#!/bin/bash
# Funció sense argumentsmostrar_data() { echo "📅 Avui és: $(date +"%d-%m-%Y %H:%M:%S")"}
# Crida a la funciómostrar_data
📝 Explicació
- La funció
mostrar_data
no rep cap argument. - Fa servir
date
per mostrar la data i l’hora en format llegible. - Es crida simplement amb
mostrar_data
.
🔹 Funció amb 1 o 2 arguments
Aquesta funció saluda un usuari.
#!/bin/bash
# Funció amb 1 o 2 argumentssaludar() { if [ $# -eq 0 ]; then echo "❌ Has d'introduir almenys un nom." return 1 fi
NOM="$1" COGNOM="${2:-}" # Opcional, buit per defecte
if [ -z "$COGNOM" ]; then echo "👋 Hola, $NOM!" else echo "👋 Hola, $NOM $COGNOM!" fi}
# Crides a la funciósaludar "Anna"saludar "Pau" "Martí"saludar # Sense arguments (error)
📝 Explicació
saludar
rep un o dos arguments.- Si no rep cap argument, mostra un missatge d’error.
- Si només es passa un nom, saluda amb aquest nom.
- Si es passen nom i cognom, saluda amb els dos.
COGNOM="${2:-}"
assegura que no hi hagi errors si només hi ha un argument.
🎯 Exercici 4: Còpia de seguretat amb funció
Descripció: Escriu un script Bash que creï una còpia de seguretat d’una carpeta i li afegeixi la data actual. Si el fitxer ja existeix, ha de mostrar un missatge i no tornar-lo a crear.
#!/bin/bash
# Funció per fer la còpia de seguretatfer_backup() { if [ $# -ne 1 ]; then echo "❌ Ús: fer_backup <carpeta_a_guardar>" return 1 fi
FOLDER="$1"
if [ ! -d "$FOLDER" ]; then echo "❌ Error: la carpeta '$FOLDER' no existeix!" return 1 fi
NOW=$(date +"%d_%m_%Y") BACKUP_FILE="${FOLDER}_backup_${NOW}.tar.gz"
if [ -f "$BACKUP_FILE" ]; then echo "ℹ️ Ja existeix un backup: $BACKUP_FILE" return 0 fi
echo "📂 Creant còpia de seguretat..." tar -czvf "$BACKUP_FILE" "$FOLDER"
if [ $? -eq 0 ]; then echo "✅ Backup creat: $BACKUP_FILE" else echo "❌ Error en crear el backup!" return 1 fi}
# Exemple d’úsfer_backup "/home/$USER/Documents"
📝 Explicació
- La funció
fer_backup
rep un argument obligatori (el directori a fer la còpia). - Comprova que el directori existeixi abans de continuar.
- Genera un fitxer
.tar.gz
amb la data actual. - Si el backup ja existeix, avisa l’usuari i no el crea de nou.
- Fa servir
tar -czvf
per comprimir la carpeta. - Gestiona errors per evitar problemes en l’execució.
💡 Prova-ho!
Executa-ho en un terminal:
./script.sh /home/usuari/Documents
Així aprens a modularitzar el teu codi amb funcions! 🚀
Recursos:
Section titled “Recursos:”Segueix amb els exemples:
El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.
©2022-2025 xtec.dev