2015-05-03 03:00:56 +03:00
---
category: tool
tool: bash
contributors:
- [ "Max Yankov" , "https://github.com/golergka" ]
- [ "Darren Lin" , "https://github.com/CogBear" ]
- [ "Alexandre Medeiros" , "http://alemedeiros.sdf.org" ]
- [ "Denis Arh" , "https://github.com/darh" ]
- [ "akirahirose" , "https://twitter.com/akirahirose" ]
- [ "Anton Strömkvist" , "http://lutic.org/" ]
- [ "Rahil Momin" , "https://github.com/iamrahil" ]
- [ "Gregrory Kielian" , "https://github.com/gskielian" ]
2016-10-03 23:14:30 +03:00
- [ "Etan Reisner" , "https://github.com/deryni" ]
- [ "Jonathan Wang" , "https://github.com/Jonathansw" ]
- [ "Leo Rudberg" , "https://github.com/LOZORD" ]
- [ "Betsy Lorton" , "https://github.com/schbetsy" ]
- [ "John Detter" , "https://github.com/jdetter" ]
2016-03-22 02:31:47 +03:00
filename: LearnBash-it.sh
2015-05-03 03:00:56 +03:00
translators:
- [ "Robert Margelli" , "http://github.com/sinkswim/" ]
2015-10-17 21:20:33 +03:00
- [ "Tommaso Pifferi" , "http://github.com/neslinesli93/" ]
2015-05-03 03:00:56 +03:00
lang: it-it
---
Bash è il nome della shell di unix, la quale è stata distribuita anche come shell del sistema oprativo GNU e la shell di default su Linux e Mac OS X.
Quasi tutti gli esempi sottostanti possono fare parte di uno shell script o eseguiti direttamente nella shell.
2015-10-17 21:20:33 +03:00
[ Per saperne di più.] ( http://www.gnu.org/software/bash/manual/bashref.html)
2015-05-03 03:00:56 +03:00
` ` ` bash
#!/bin/bash
# La prima riga dello script è lo shebang il quale dice al sistema come eseguire
# lo script: http://it.wikipedia.org/wiki/Shabang
# Come avrai già immaginato, i commenti iniziano con #. Lo shebang stesso è un commento.
# Semplice esempio ciao mondo:
echo Ciao mondo!
# Ogni comando inizia su una nuova riga, o dopo un punto e virgola:
echo 'Questa è la prima riga' ; echo 'Questa è la seconda riga'
# Per dichiarare una variabile:
2015-10-17 21:20:33 +03:00
Variabile = "Una stringa"
2015-05-03 03:00:56 +03:00
# Ma non così:
2015-10-17 21:20:33 +03:00
Variabile = "Una stringa"
# Bash stabilirà che Variabile è un comando da eseguire e darà un errore
2015-05-03 03:00:56 +03:00
# perchè non esiste.
# Usare la variabile:
2015-10-17 21:20:33 +03:00
echo $Variabile
echo " $Variabile "
echo '$Variabile'
2015-05-03 03:00:56 +03:00
# Quando usi la variabile stessa - assegnala, esportala, oppure — scrivi
# il suo nome senza $. Se vuoi usare il valore della variabile, devi usare $.
# Nota che ' (singolo apice) non espande le variabili!
2016-10-03 23:14:30 +03:00
# Espansione dei parametri ${ }:
echo ${ Variabile }
# Questo è un esempio semplice dell'espansione dei parametri.
# L'espansione dei parametri prende il valore di una variabile, ed appunto lo "espande" o lo stampa.
# Durante l'espansione il valore o il parametro passato possono essere modificati.
# Sotto ci sono altri esempi che analizzano l'uso dell'espansione dei parametri.
2015-05-03 03:00:56 +03:00
# Sostituzione di stringhe nelle variabili
2020-01-29 10:43:27 +03:00
echo ${ Variabile /Una/La }
2015-05-03 03:00:56 +03:00
# Questo sostituirà la prima occorrenza di "Una" con "La"
# Sottostringa di una variabile
2015-10-17 21:20:33 +03:00
Lunghezza = 7
echo ${ Variabile : 0 : Lunghezza }
2015-05-03 03:24:45 +03:00
# Questo ritornerà solamente i primi 7 caratteri
2015-05-03 03:00:56 +03:00
# Valore di default per la variabile
2015-10-17 21:20:33 +03:00
echo ${ Foo :- "ValoreDiDefaultSeFooMancaOppureÈVuoto" }
# Questo funziona per null (Foo=), stringa vuota (Foo=""), zero (Foo=0) ritorna 0
# Nota: viene ritornato il valore di default, il contenuto della variabile pero' non cambia.
2015-05-03 03:00:56 +03:00
2016-10-03 23:14:30 +03:00
# Espansione delle graffe { }
# Viene usata per generare stringe in modo arbitrario
echo { 1..10}
echo { a..z}
# Con questi comandi viene stampato l'intervallo dal valore iniziale al valore finale (i numeri da 1 a 10, le lettere dell'alfabeto)
2015-05-03 03:00:56 +03:00
# Variabili builtin:
# Ci sono delle variabili builtin molto utili, come
echo " Valore di ritorno dell'ultimo programma eseguito: $? "
echo " PID dello script: $$ "
echo " Numero di argomenti: $# "
echo " Argomenti dello script: $@ "
echo " Argomenti dello script separati in variabili distinte: $1 $2 ... "
2016-10-03 23:14:30 +03:00
# Adesso che sappiamo come stampare a schermo, e come usare le variabili, possiamo andare avanti con le basi di bash!
# Per conoscere la directory su cui siamo posizionati, è sufficiente usare `pwd`.
# `pwd` è l'acronimo di "print working directory", ovvero "stampa la directory corrente".
# Possiamo anche usare la variabile builtin `$PWD`.
# Prova questi due esempi, e vedi che il risultato è lo stesso:
echo " Sono dentro $( pwd ) " # esegue `pwd` ed interpola l'output
echo " Sono dentro $PWD " # interpola direttamente la variabile builtin
# Se c'è troppo testo nel terminale, ottenuto scrivendo comandi oppure eseguendo uno script, il comando `clear` pulisce lo schermo
clear
# Puoi utilizzare anche Ctrl-L al posto di clear
2015-05-03 03:00:56 +03:00
# Leggere un valore di input:
echo "Come ti chiami?"
2015-10-17 21:20:33 +03:00
read Nome # Nota che non abbiamo dovuto dichiarare una nuova variabile
echo Ciao, $Nome !
2015-05-03 03:00:56 +03:00
# Classica struttura if:
# usa 'man test' per maggiori informazioni sulle condizionali
2015-10-17 21:20:33 +03:00
if [ $Nome -ne $USER ]
2015-05-03 03:00:56 +03:00
then
echo "Il tuo nome non è lo username"
else
echo "Il tuo nome è lo username"
fi
2015-10-17 21:20:33 +03:00
# Nota: se $Name è vuoto, la condizione precedente viene interpretata come:
if [ -ne $USER ]
# che genera un errore di sintassi. Quindi il metodo sicuro per usare
# variabili che possono contenere stringhe vuote è il seguente:
if [ " $Name " -ne $USER ] ...
# che viene interpretato come:
if [ "" -ne $USER ] ...
# e dunque funziona correttamente.
2015-05-03 03:00:56 +03:00
# C'è anche l'esecuzione condizionale
echo "Sempre eseguito" || echo "Eseguito solo se la prima condizione fallisce"
echo "Sempre eseguito" && echo "Eseguito solo se la prima condizione NON fallisce"
# Per usare && e || con l'if, c'è bisogno di piu' paia di parentesi quadre:
2015-10-17 21:20:33 +03:00
if [ " $Nome " = = "Steve" ] && [ " $Eta " -eq 15 ]
2015-05-03 03:00:56 +03:00
then
2015-10-17 21:20:33 +03:00
echo " Questo verrà eseguito se $Nome è Steve E $Eta è 15. "
2015-05-03 03:00:56 +03:00
fi
2015-10-17 21:20:33 +03:00
if [ " $Nome " = = "Daniya" ] || [ " $Nome " = = "Zach" ]
2015-05-03 03:00:56 +03:00
then
2015-10-17 21:20:33 +03:00
echo " Questo verrà eseguito se $Nome è Daniya O Zach. "
2015-05-03 03:00:56 +03:00
fi
2019-10-05 22:19:37 +03:00
# C'è anche l'operatore `=~`, che serve per confrontare una stringa con un'espressione regolare:
Email = me@example.com
if [ [ " $Email " = ~ [ a-z] +@[ a-z] { 2,} \. ( com| net| org) ] ]
then
echo "Email valida!"
fi
# L'operatore =~ funziona solo dentro alle doppie parentesi quadre [[ ]],
# che hanno un comportamento leggermente diverso rispetto alle singole [ ].
# Se vuoi approfondire, visita questo link (in inglese):
# http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs
# Usando `alias`, puoi definire nuovi comandi o modificare quelli già esistenti.
# Ad esempio, così puoi ridefinire il comando ping per inviare solo 5 pacchetti
alias ping = 'ping -c 5'
# "Scavalca" l'alias e usa il comando vero, utilizzando il backslash
\p ing 192.168.1.1
# Stampa la lista di tutti gli alias
alias -p
2015-05-03 03:00:56 +03:00
# Le espressioni sono nel seguente formato:
echo $(( 10 + 5 ))
# A differenza di altri linguaggi di programmazione, bash è una shell - quindi lavora nel contesto
# della cartella corrente. Puoi elencare i file e le cartelle nella cartella
# corrente con il comando ls:
ls
# Questi comandi hanno opzioni che controllano la loro esecuzione:
ls -l # Elenca tutti i file e le cartelle su una riga separata
2016-10-03 23:14:30 +03:00
ls -t # Ordina i contenuti della cartella in base all'ultima data di modifica (ordine decrescente)
ls -R # Esegue `ls` in modo ricorsivo all'interno di questa cartella e tutte le sottocartelle
2015-05-03 03:00:56 +03:00
# I risultati del comando precedente possono essere passati al comando successivo come input.
# Il comando grep filtra l'input con il pattern passato. Ecco come possiamo elencare i
# file .txt nella cartella corrente:
ls -l | grep "\.txt"
2016-10-03 23:14:30 +03:00
# Usa `cat` per stampare il contenuto dei file a schermo:
cat file.txt
# Possiamo leggere il contenuto di un file e memorizzarlo in una variabile, sempre usando `cat`:
Contenuti = $( cat file.txt)
echo " INIZIO DEL FILE\n $Contenuti \nFINE DEL FILE "
# Usa `cp` per copiare file o cartelle da un punto all'altro del sistema.
# `cp` crea NUOVE versioni dei file, quindi le modifiche della copia non hanno effetto sull'originale, e viceversa.
# Nota che il file (o la cartella) di destinazione vengono sovrascritte se già esistono!
cp fileSorgente.txt copia.txt
cp -r cartellaSorgente/ destinazione/ # copia ricorsiva
# Se hai bisogno di trasferire file tra computer, puoi usare `scp` o `sftp`.
# `scp` ha una sintassi simile a `cp`.
# `sftp` invece è più interattivo.
# Usa `mv` per spostare file o cartella da un punto all'altro del sistema.
# `mv` è simile a `cp`, ma cancella il file(o la cartella) sorgente.
# `mv` è molto utile anche per rinominare i file!
mv s0rg3nt3.txt dst.txt # mi spiace anonymous...
# Dal momento che bash lavora nel contesto della cartella corrente, potresti voler eseguire il comando dentro a qualche altra cartella. Per fare questo si usa `cd`:
cd ~ # va nella cartella Home
cd .. # va nella cartella "padre"
# (ad esempio da /home/user/Download a /home/user)
cd /home/user/Documenti # entra nella cartella specificata
cd ~/Documenti/.. # siamo sempre nella cartella home... vero?
# Usa le subshell per lavorare in cartelle diverse contemporaneamente
( echo " All'inizio sono qua: $PWD " ) && ( cd cartella; echo " Adesso invece sono qua: $PWD " )
pwd # siamo sempre nella prima cartella
# Usa `mkdir` per creare nuove cartelle
mkdir nuovaCartella
# Il flag `-p` indica la creazione delle cartelle intermedie, se non esistono.
mkdir nuovaCartella/con/tante/cartelle/intermedie
2015-05-03 03:00:56 +03:00
# Puoi redirezionare l'input e l'output del comando (stdin, stdout, e stderr).
# Leggi da stdin finchè ^EOF$ e sovrascrivi hello.py con le righe
# comprese tra "EOF":
cat > hello.py << EOF
#!/usr/bin/env python
from __future__ import print_function
import sys
print( "#stdout" , file = sys.stdout)
print( "#stderr" , file = sys.stderr)
for line in sys.stdin:
print( line, file = sys.stdout)
EOF
# Esegui hello.py con diverse redirezioni stdin, stdout, e stderr:
python hello.py < "input.in"
python hello.py > "output.out"
python hello.py 2> "error.err"
python hello.py > "output-and-error.log" 2>& 1
python hello.py > /dev/null 2>& 1
# Lo output error sovrascriverà il file se esiste,
# se invece vuoi appendere usa ">>":
python hello.py >> "output.out" 2>> "error.err"
2015-10-17 21:20:33 +03:00
# Sovrascrivi output.out, appendi a error.err, e conta le righe:
2015-05-03 03:00:56 +03:00
info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err
wc -l output.out error.err
# Esegui un comando e stampa il suo file descriptor (esempio: /dev/fd/123)
# vedi: man fd
echo <( echo "#ciaomondo" )
2015-10-17 21:20:33 +03:00
# Sovrascrivi output.out con "#helloworld":
2015-05-03 03:00:56 +03:00
cat > output.out <( echo "#helloworld" )
echo "#helloworld" > output.out
echo "#helloworld" | cat > output.out
echo "#helloworld" | tee output.out >/dev/null
# Pulisci i file temporanei verbosamente (aggiungi '-i' per la modalità interattiva)
2016-10-03 23:14:30 +03:00
# Attenzione: il comando `rm` non può essere annullato!
2015-05-03 03:00:56 +03:00
rm -v output.out error.err output-and-error.log
2016-10-03 23:14:30 +03:00
rm -r cartellaTemporanea/ # cancella ricorsivamente
2015-05-03 03:00:56 +03:00
# I comandi possono essere sostituiti con altri comandi usando $( ):
# Il comando seguente mostra il numero di file e cartelle nella
# cartella corrente.
echo " Ci sono $( ls | wc -l) oggetti qui. "
# Lo stesso puo' essere usato usando backticks `` ma non possono essere innestati - il modo migliore
# è usando $( ).
echo "Ci sono `ls | wc -l` oggetti qui."
# Bash utilizza uno statemente case che funziona in maniera simile allo switch in Java e C++:
2015-10-17 21:20:33 +03:00
case " $Variabile " in
2015-05-03 03:00:56 +03:00
#Lista di pattern per le condizioni che vuoi soddisfare
0) echo "C'è uno zero." ; ;
1) echo "C'è un uno." ; ;
*) echo "Non è null." ; ;
esac
# I cicli for iterano per ogni argomento fornito:
2015-10-17 21:20:33 +03:00
# I contenuti di $Variabile sono stampati tre volte.
for Variabile in { 1..3}
2015-05-03 03:00:56 +03:00
do
2015-10-17 21:20:33 +03:00
echo " $Variabile "
2015-05-03 03:00:56 +03:00
done
# O scrivilo con il "ciclo for tradizionale":
for ( ( a = 1; a <= 3; a++) )
do
echo $a
done
# Possono essere usati anche per agire su file..
# Questo eseguirà il comando 'cat' su file1 e file2
2015-10-17 21:20:33 +03:00
for Variabile in file1 file2
2015-05-03 03:00:56 +03:00
do
2015-10-17 21:20:33 +03:00
cat " $Variabile "
2015-05-03 03:00:56 +03:00
done
# ..o dall'output di un comando
# Questo eseguirà cat sull'output di ls.
2015-10-17 21:20:33 +03:00
for Output in $( ls)
2015-05-03 03:00:56 +03:00
do
2015-10-17 21:20:33 +03:00
cat " $Output "
2015-05-03 03:00:56 +03:00
done
# while loop:
while [ true ]
do
echo "corpo del loop..."
break
done
# Puoi anche definire funzioni
# Definizione:
function foo ( )
{
echo " Gli argomenti funzionano come gli argomenti dello script: $@ "
echo " E: $1 $2 ... "
echo "Questa è una funzione"
return 0
}
# o semplicemente
bar ( )
{
echo "Un altro modo per dichiarare funzioni!"
return 0
}
# Per chiamare la funzione
2015-10-17 21:20:33 +03:00
foo "Il mio nome è" $Nome
2015-05-03 03:00:56 +03:00
# Ci sono un sacco di comandi utili che dovresti imparare:
# stampa le ultime 10 righe di file.txt
tail -n 10 file.txt
# stampa le prime 10 righe di file.txt
head -n 10 file.txt
# ordina le righe di file.txt
sort file.txt
# riporta o ometti le righe ripetute, con -d le riporta
uniq -d file.txt
# stampa solamente la prima colonna prima del carattere ','
cut -d ',' -f 1 file.txt
# sostituisce ogni occorrenza di 'okay' con 'great' in file.txt (compatible con le regex)
sed -i 's/okay/great/g' file.txt
# stampa su stdout tutte le righe di file.txt che soddisfano una certa regex
# L'esempio stampa le righe che iniziano con "foo" e che finiscono con "bar"
grep " ^foo.*bar $" file.txt
# passa l'opzione "-c" per stampare invece il numero delle righe che soddisfano la regex
grep -c " ^foo.*bar $" file.txt
2016-10-03 23:14:30 +03:00
# Altre opzioni utili possono essere:
grep -r " ^foo.*bar $" someDir/ # esegue `grep` ricorsivamente nella cartella
grep -n " ^foo.*bar $" file.txt # stampa il numero delle righe del file
grep -rI " ^foo.*bar $" someDir/ # esegue `grep` ricorsivamente nella cartella, ignorando i file non testuali
# Esegue la stessa ricerca iniziale, ma filtrando solo le righe che contengono la stringa "baz"
grep " ^foo.*bar $" file.txt | grep -v "baz"
2015-05-03 03:00:56 +03:00
# se vuoi letteralmente cercare la stringa,
# e non la regex, usa fgrep (o grep -F)
2016-10-03 23:14:30 +03:00
fgrep "foobar" file.txt
# Il comando trap permette di eseguire un comando quando un segnale viene ricevuto dal tuo script.
# In questo esempio, trap eseguirà rm se uno dei tre segnali (SIGHUP, SIGINT o SIGTERM) viene ricevuto.
trap " rm $TEMP_FILE ; exit " SIGHUP SIGINT SIGTERM
2015-05-03 03:00:56 +03:00
2016-10-03 23:14:30 +03:00
# `sudo` viene usato per eseguire comandi come superuser, ovvero come utente che ha maggiori privilegi all'interno del sistema
$NOME1 = $( whoami)
$NOME2 = $( sudo whoami)
echo " Ero $NOME1 , poi sono diventato più potente: $NOME2 "
2015-05-03 03:00:56 +03:00
# Leggi la documentazione dei builtin di bash con il builtin 'help' di bash:
help
help help
help for
help return
help source
help .
# Leggi la manpage di bash con man
apropos bash
man 1 bash
man bash
# Leggi la documentazione con info (? per help)
apropos info | grep '^info.*('
man info
info info
info 5 info
# Leggi la documentazione di bash:
info bash
info bash 'Bash Features'
info bash 6
info --apropos bash
` ` `