Rinominare un gruppo di file in base ad una regexpr
Supponiamo di voler rinominare il nome di un gruppo di file che hanno il seguente template:
file1_tmp.sh
file2_tmp.sh
...
file99_tmp.sh
e supponiamo di voler togliere la parte centrale ‘_tmp’ in tutti i file. Possiamo utilizzare il comando “rename” o “prename”:
rename 's/_tmp//' *.sh
Vedi tutte le FAQs
Redirigere lo standard error sullo standart output
Per redirigere lo standard error di un comando in shell basta utilizzare la seguente sinstassi seguente:
ls file_non_esistente 2>&1 | grep File
oppure ancor meglio per non avere sul terminale lo standard error basta buttarlo in /dev/null
ls file_non_esistente 2>/dev/null
Gli identificativi standard o canali standard (o standard streams) aperti automaticamente sono:
- 0 standard input
- 1 standard output
- 2 standard error
Vedi tutte le FAQs
Uso di array semplici in bash
Con Bash per dichiarare esplicitamente un array bisogna utilizzare
declare -A mioarray
Per avere il valore dell’elemento 5 basta scrivere
echo $[mioarray[5]
mentre per cambiare il valore bisogna scrivere
mioarray[5]='nuovo valore'
${mioarray[*]} o ${mioarray[@]} viene espanso da tutti i valori dell’array mentre $[#mionome[@]} viene espanso con la lunghezza dell’array
Cosa possiamo fare con gli array? Ad esempio memorizzare l’output di un comando di cui ogni riga vorremmo che vada su un elemento differente.
IFS=$'\n' mioarray=($(ls -alh))
A questo punto possiamo stampare l’output come
IFS=$'\n' echo "${mioarray[*]}"
Attenzione: i doppi apici sono importanti per non avere l’output su un’unica riga.
Facendo così potremmo fare diversi test sullo stesso output catturato una sola volta.
Vedi tutte le FAQs
Uso di array associativi in bash
Per dichiarare un array associativo bisogna dichiararlo con
declare -A mioarray/
e come indice si può utilizzare una stringa, questo significa che
mioarray[test]='aa'
echo ${mioarray[test]} # restituisce 'aa'
Vedi tutte le FAQs
Convertire da Bash un numero decimale in binario
Supponiamo di star lavorando su uno script bash e che per qualche esigenza, nemmeno troppo difficile dalla realtà, sia indispensabile dover convertire un numero o una variabile decimale in numero binario.
Ci sono naturalmente diverse soluzioni ma quella che vi propongo non fa utilizzo di programmi esterni ma è bash a tutti gli effetti.
Per prima cosa dobbiamo sapere il valore massimo del numero binario da ottenere in Bash ovvero in quanti bit potrà essere compreso.
Consideriamo che stiamo parlando di un byte e quindi 8 bit e cioè il numero binario andrà da 00000000 a 11111111 (da 0 a 255) allora possiamo scrivere:
bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
echo ${bin[*]}

Il più è fatto, infatti per avere il risultato ad esempio del numero 125 o di 78 in binario basta semplicemente
echo ${bin[125]}
01111101
echo ${bin[78]}
01001110
Se cambia il range del numero binario ad esempio se raddoppiamo o quadruplichiamo basta che definiamo la variabile bin con uno o due blocchi in più del tipo {0..1}.
Quindi riassumendo, la variabile bin dovrà contenere tanti blocchi {0..1} in base al numero massimo binario che si vuole ottenere cioè se il massimo numero è 2n -1 allora ci vorranno n gruppi {0..1}.
Come esempio se n=10 e quindi 210 -1=1023 i blocchi saranno 10
bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
echo ${bin[1023]}
1111111111
Vedi tutte le FAQsConvertire da Bash un numero decimale in esadecimale
Come per la faq con la conversione in binario anche in questa facciamo utilizzo delle fantastiche estensioni bash sulle parentisi graffe per convertire in esadecimale.
Quindi, considerando sempre la faq bash sul binario partiamo inizialmente con il convertire un numero decimale tra 0 e 255 che corrisponde ad una cifra esadecimale tra 0 ed FF:
hex=({{0..9},{a..f}}{{0..9},{a..f}})
echo ${hex[*]}

A questo punto per avere il risultato del numero 200 oppure di 21 basta
echo ${hex[200]}
c8
echo ${hex[21]}
15
Se cambia il range del numero esadecimale ad esempio se raddoppiamo o quadruplichiamo basta che definiamo la variabile hex con uno o due blocchi in più del tipo {0..9},{a..f}.
Quindi riassumendo, la variabile hex dovrà contenere tanti blocchi {0..9},{a..f} in base al numero massimo binario che si vuole ottenere cioè se il massimo numero è 16n -1 allora ci vorranno n gruppi {0..9},{a..f}.
Come esempio se n=4 e quindi 164 -1=65535 i blocchi saranno 4
hex=({{0..9},{a..f}}{{0..9},{a..f}}{{0..9},{a..f}}{{0..9},{a..f}})
echo ${hex[60000]}
ea60
echo ${hex[37]}
0025
Vedi tutte le FAQsCome convertire una netmask IPV4 in CIDR
Per passare da una netmask IPV4 a l’equivalente CIDR potrebbe venir in mente di fare la cosa più semplice ovvero utilizzare un blocco case o degli if annidati per ottenere il CIDR equivalente tanto i netmask o CIDR disponibili sono solo 32 e cioè
Netmask | Address/CIDR | Adresses |
255.255.255.255 | a.b.c.d/32 | 20 |
255.255.255.254 | a.b.c.d/31 | 20 |
255.255.255.252 | a.b.c.d/30 | 21 |
255.255.255.248 | a.b.c.d/29 | 22 |
255.255.255.240 | a.b.c.d/28 | 23 |
255.255.255.224 | a.b.c.d/27 | 24 |
255.255.255.192 | a.b.c.d/26 | 25 |
255.255.255.128 | a.b.c.d/25 | 26 |
255.255.255.0 | a.b.c.0/24 | 27 |
255.255.254.0 | a.b.c.0/23 | 28 |
255.255.252.0 | a.b.c.0/22 | 29 |
255.255.248.0 | a.b.c.0/21 | 210 |
255.255.240.0 | a.b.c.0/20 | 212 |
255.255.224.0 | a.b.c.0/19 | 213 |
255.255.192.0 | a.b.c.0/18 | 214 |
255.255.128.0 | a.b.c.0/17 | 215 |
255.255.0.0 | a.b.0.0/16 | 216 |
255.254.0.0 | a.b.0.0/15 | 217 |
255.252.0.0 | a.b.0.0/14 | 218 |
255.248.0.0 | a.b.0.0/13 | 219 |
255.240.0.0 | a.b.0.0/12 | 220 |
255.224.0.0 | a.b.0.0/11 | 221 |
255.192.0.0 | a.b.0.0/10 | 222 |
255.128.0.0 | a.b.0.0/9 | 223 |
255.0.0.0 | a.0.0.0/8 | 224 |
254.0.0.0 | a.0.0.0/7 | 225 |
252.0.0.0 | a.0.0.0/6 | 226 |
248.0.0.0 | a.0.0.0/5 | 227 |
240.0.0.0 | a.0.0.0/4 | 228 |
224.0.0.0 | a.0.0.0/3 | 229 |
192.0.0.0 | a.0.0.0/2 | 230 |
128.0.0.0 | a.0.0.0/1 | 231 |
0.0.0.0 | 0.0.0.0/0 | 232 |
Se vogliamo, invece, realizzare una funzione che converta il netmask in CIDR abbiamo bisogno di sapere come convertire un numero decimale in binario come prima cosa.
fromNetmaskToCidr() {
local netmask=$1
local bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
local b=''
local n
local cidr
for n in ${netmask//./ }; do
if [ $n -gt 255 ]; then
echo -e "\t[ERROR] netmask $netmask format error in '.$n'. I will use .255 insted of .$n"
n=255
fi
if [ $n -ne 0 -a $n -ne 128 -a $n -ne 192 -a $n -ne 224 -a $n -ne 240 -a $n -ne 248 -a $n -ne 252 -a $n -ne 254 -a $n -ne 255 ]; then
echo -e "\t[ERROR] netmask $netmask format error in '.$n' (it must be 0,128,192,224,240,248,252,254,255). I will use .255 insted of .$n"
n=255
fi
# $b is the binary of $netmask
b=${b}${bin[$n]}
done
# remove right "0" bits from $b
b=${b/%0*}
cidr=${#b}
echo $cidr
}
Quel che si fa è convertire i 4 ottetti del netmask in binario e metterli in serie nell’unica variabile “b” quindi rimuovere i bit a 0 presenti nella destra del numero binario complessivo.
Infine basta contare il numero dei bit rimasti per avere il CIDR che poi verrà restituito in uscita.