1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
|
---
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"]
- ["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"]
filename: LearnBash-it.sh
translators:
- ["Robert Margelli", "http://github.com/sinkswim/"]
- ["Tommaso Pifferi", "http://github.com/neslinesli93/"]
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.
[Per saperne di più.](http://www.gnu.org/software/bash/manual/bashref.html)
```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:
Variabile="Una stringa"
# Ma non così:
Variabile = "Una stringa"
# Bash stabilirà che Variabile è un comando da eseguire e darà un errore
# perchè non esiste.
# Usare la variabile:
echo $Variabile
echo "$Variabile"
echo '$Variabile'
# 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!
# 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.
# Sostituzione di stringhe nelle variabili
echo ${Variabile/Una/La}
# Questo sostituirà la prima occorrenza di "Una" con "La"
# Sottostringa di una variabile
Lunghezza=7
echo ${Variabile:0:Lunghezza}
# Questo ritornerà solamente i primi 7 caratteri
# Valore di default per la variabile
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.
# 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)
# 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..."
# 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
# Leggere un valore di input:
echo "Come ti chiami?"
read Nome # Nota che non abbiamo dovuto dichiarare una nuova variabile
echo Ciao, $Nome!
# Classica struttura if:
# usa 'man test' per maggiori informazioni sulle condizionali
if [ $Nome -ne $USER ]
then
echo "Il tuo nome non è lo username"
else
echo "Il tuo nome è lo username"
fi
# 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.
# 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:
if [ "$Nome" == "Steve" ] && [ "$Eta" -eq 15 ]
then
echo "Questo verrà eseguito se $Nome è Steve E $Eta è 15."
fi
if [ "$Nome" == "Daniya" ] || [ "$Nome" == "Zach" ]
then
echo "Questo verrà eseguito se $Nome è Daniya O Zach."
fi
# 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
\ping 192.168.1.1
# Stampa la lista di tutti gli alias
alias -p
# 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
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
# 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"
# 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
# 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"
# Sovrascrivi output.out, appendi a error.err, e conta le righe:
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")
# Sovrascrivi output.out con "#helloworld":
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)
# Attenzione: il comando `rm` non può essere annullato!
rm -v output.out error.err output-and-error.log
rm -r cartellaTemporanea/ # cancella ricorsivamente
# 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++:
case "$Variabile" in
#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:
# I contenuti di $Variabile sono stampati tre volte.
for Variabile in {1..3}
do
echo "$Variabile"
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
for Variabile in file1 file2
do
cat "$Variabile"
done
# ..o dall'output di un comando
# Questo eseguirà cat sull'output di ls.
for Output in $(ls)
do
cat "$Output"
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
foo "Il mio nome è" $Nome
# 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
# 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"
# se vuoi letteralmente cercare la stringa,
# e non la regex, usa fgrep (o grep -F)
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
# `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"
# 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
```
|