Nei sistemi GNU/Linux esistono diverse tipologie di file, uno schema può essere visionato nella tabella sottostante:
| Tipo di File | Descrizione |
|---|---|
| file regolare | file che contiene dei dati (l'accezione normale di file) |
| cartella o direttorio | file che contiene una lista di nomi associati a degli inode |
| collegamento simbolico | file che contiene un riferimento ad un altro file/directory |
| dispositivo a caratteri | file che identifica una periferica ad accesso a caratteri |
| dispositivo a blocchi | file che identifica una periferica ad accesso a blocchi |
| "coda" (o fifo) | file speciale che identifica una linea di comunicazione software unidirezionale |
| "presa" (o socket) | file speciale che identifica una linea di comunicazione software bidirezionale |
Le tipologie per noi di maggiore interesse sono le prime tre, siccome conosciamo già abbastanza bene il concetto di file e il concetto di directory, nella prossima sezione parleremo di collegamenti (o link).
Esistono due modalità per creare dei collegamenti (o "link") sui sistemi GNU/Linux:
- Soft Link
- Hard Link
le differenze sono:
- Gli hard link possono vivere solo sullo stesso filesystem
- Se rimuovo una copia di un hard link, l'altra continua a sopravvivere
- Nel caso di soft link, se rimuovo la copia originale, l'altra muore
Gli Hard Link sono simili ad una copia, ma si aggiornano quando viene effettuata una modifica su uno dei link. Per creare un Hard Link facciamo:
ln sourceFile nameofTheHardLink
# crea un hard linkPer creare un Soft Link facciamo:
ln -s sourceFile nameOfTheSoftLink
# crea un soft linkEsistono ovviamente anche altri flag aggiuntivi che possono essere utilizzati ad esempio:
-i
# chiede conferma prima della creazione -f
# forza la creazione di un linkPer rimuovere un link basta effettuare:
unlink nomeFileODirectory
# rimuove il link al file o alla
# directoryATTENZIONE: non provare assolutamente a rimuovere link a directory utilizzando rm -R sul link della directory, questo provocherà la rimozione dei file reali e non del link.
I comandi più comunemente utilizzati per cercare file su linux sono:
- find
- locate
Anche se è possibile effettuare ricerche di file anche con un appropriato utilizzo dei comandi "grep" ed "ls".
Vediamo alcuni esempi di applicazione del programma find:
find /etc -name motd
# questo comando cercherà nella directory
# /etc (e sue sottodirectory) un file che ha nel nome la parola "
# motd".il comando find è lento (rispetto a locate), ma molto efficace in quando scandisce i file uno ad uno. E' molto probabile non avere i permessi di lettura in alcune directory (almenochè non si è l'utente root) in questo caso, vedremo molti messaggi a schermo provenienti dallo standard error, per evitare di stampare questi messaggi a schermo possiamo fare uso del seguente comando:
find /etc -name motd 2>/dev/nullAltri esempi di applicazione del comando find possono essere:
find /home/john -name "*.jpg"
# cerca nella directory
# /home/john, tutti i file con estensione .jpg find /etc -perm 777
# cerca nella directory /etc tutti i file
# con permessi 777, questa operazione potrebbe essere utile per
# salvaguardare la macchina, in modo da non esporre a tutti, file
# sensibili.Un'altra utile possibilità risiede nel poter effettuare delle operazioni specifiche con i file trovati, ad esempio:
find /home -perm 777 -exec chmod 555 {} \;
# questo comando,
# una volta lanciato, troverà tutti i file con permessi 777 e li
# cambierà a 555, questa operazione viene effettuata per ogni
# file trovato; la parola chiave "-exec" indica l'inizio di un
# comando, le parantesi graffe {} indicano "ogni file trovato" e "
# \;" indica la fine del comando. find / -size 30M
# questo comando mi troverà file grossi fino a
# 30MB find / -type f -size +500M
# questo comando troverà file di
# grandezza maggiore a 500MBE' possibile anche impostare una determinata profondità nelle ricerche, ad esempio:
find /etc -maxdepth 1
# effettua ricerche fino a una
# sottodirectory di profonditàpossiamo ricercare anche in funzione di nomi utente o di gruppo (o codice utente/gruppo); infatti altri esempi potrebbero essere:
find /home -user john
# elenca i file appertenenti all'utente "
# John" nella directory /home find . -type f -name 'cron*'
# in questo esempio vengono
# evidenziati solo i file che iniziano per "cron" e non le
# directory, arreaverso il flag "-type f" find . -type d -name 'cron*'
# in questo altro caso invece
# vengono cercate solo le directory che iniziano per "cron" find / -mtime +1
# se vogliamo cercare i file modificati
# nell'ultimo giorno, un'alternativa ad "-mtime" è "-a", per
# effettuare le stesse funzioni find / -group nameofgroup
# evidenzia tutti i file di un
# determinato gruppo find . -name 'file*' -exec rm {} \;
# elimina tutti i file che
# iniziano per la parola "file", questo può essere utile nel caso
# dovessimo eliminare una lista di file con nomi simili find ~/Movies/ -size +1024M
# cerca file di dimensioni oltre
# 1GB (1024MB) nella directory menzionata find / -size 50M
# trova tutti i file che hanno una dimensione
# esattamente di 50MB find / -size 33c
# trova tutti i file di 33 byte, infatti il
# suffisso "c" sta per byte, mentre l'opzione di default (cioè se
# non avessi messo la 'c') sarebbe stata "b" che sta per blocco,
# dove per blocco si intendono blocchi da 512byte cadauno find . -size 1033c ! -executable
# mostra tutti i file che sono
# grandi 1033bytes e non sono eseguibili find / -size +50M -size -100M
# trova tutti i file che hanno
# una dimensione maggiore a 50MB ma minore a 100MB find / -type f -name *.mp3 -size +10M -exec rm {} \;
# trova
# tutti i file mp3 con dimensione maggiore a 10MB e li elimina find ~ -perm 777
# cerca tutti i file nella directory utente
# con pieni permessi find . -user daniel -type f -name *.jpg ! -name autumn*
# trova
# tutti i file dell'utente daniel, con estensione jpg ma che non
# contengono la stringa "autumn" nel nome find ~/scripts/ -user root -type f -amin -2 -name *.rb
# trova
# gli script ruby (.rb) a cui abbiamo fatto accesso negli ultimi
# 2 minuti find ~/scripts/ -user root -type f -mmin -2 -name *.rb
# trova
# gli script ruby (.rb) che abbiamo modificato negli ultimi 2
# minuti find /tmp -type f -empty
# cerca tutti i file vuoti find /tmp -type f -name ".*"
# cerca tutti i file nascosti find / -mtime +50 --mtime -100
# trova tutti i file che sono
# stati cambiati più di 50 giorni fa ma non più di 100 giorni fa find / -mmin -60
# trova tutti i file modificati nell'ultima
# ora find / -perm -4000 2>/dev/null
# in questo modo cerchiamo tutti
# i file con setuid, questi possono essere utili nell'ambito
# della sicurezza per effettuare privilege escalation, quindi
# fare attenzione a questi filePossiamo anche usare find per trovare i file duplicati con:
find -type f -exec md5sum '{}' ';' | sort | uniq --all-repeated=separate -w 33Un modo comune con cui utilizzare find per cercare file utilizzando regex e':
find . | grep -i 'filename or regex'
# in questo modo cerchiamo dalla directory correnteo con semplici varianti per selezionare solo file o directory con:
find . -type f| grep -i 'filename or regex'
# in questo modo cerchiamo dalla directory corrente
# ma solo i file che non sono directory find . -type d | grep -i 'filename or regex'
# in questo modo cerchiamo dalla directory corrente
# ma solo le directoryPossiamo anche cercare tramite regex su GNU find facendo:
find . -type f -regextype posix-extended -regex '.*\.md{3}'
# This is a match on the whole path, not a search.
# For example, to match a file named './fubar3',
# you can use the regular expression '.*bar.' or '.*b.*3', but not 'b.*r3'.Possiamo anche escludere determinati path utilizzando l'"OR" logico e l'opzione "prune" in questo modo:
find / \( -path /dev -prune -o \
-path /proc -prune -o \
-path /sys -prune \
\) \
-o -printf '%p ' -exec cksum {} \;
# Find all files and compute checksum but exclude the paths /dev /proc /sys Locate è un programma che crea un indice dei file salvati sul sistema all'interno di un database. Quando viene effettuata una ricerca, locate cercherà all'interno del database, quindi le ricerche sono molto veloci. Normalmente il database viene aggiornato ogni ora, ma questo dipende dalla configurazione, quest'azione periodica può anche essere visualizzata in cron. Possiamo aggiornare manualmente il database attraverso il comando
updatedb
# aggiorna il database di locateAltri esempi di utilizzo possono essere:
locate fileName
# cerca il file chiamato "filename" locate physics | grep -i "/DATA"
# questo cercherà i file
# chiamati "physics" che sono situati nella directory "/DATA"Nota Bene: Se un file viene creato e istantaneamente viene cercato, locate non riesce a trovarlo in quanto il database non è stato aggiornato.
Il file di configurazione per il database è localizzato in " /etc/updatedb.conf".
Vediamo ora alcune impostazioni importanti all'interno del file "/etc/updatedb.conf"
PRUNE_BIND_MOUNTS = "yes"
# questa opzione permette di mettere
# in gioco all'interno del database anche i filesystem connessi
# al sistema principale PRUNEFS = "... ... ..."
# qui sono elencati i tipi di
# filesystem da ignorare e quindi non catalogare nel database PRUNENAMES = ".git .hg .svn"
# le estensioni da escludere nelle
# ricerche PRUNEPATHS = "/afs /media"
# le directory da escludere nelle
# ricercheVerranno di sequito elencate alcune modalità alternative per effettuare ricerche di file su sistemi GNU/Linux:
ls /nomeDirectoryInCuiCercare -R | grep "nomeFileOWildCard"
# cerca in modo ricorsivo (dir e subdirs) all'interno della
# directory /nomeDirectoryInCuiCercare i file che hanno nome
# nomeFileOWildCard grep -lr nomeFile /directory
# elenca i file i cui nomi
# corrispondono a nomeFile all'interno della directory /directoryTar è un programma utilizzato per archiviare (o raggruppare) più file in un singolo file, i file creati con tar sono chiamati " tarball", questo ci permette di maneggiare insiemi di file e directory come se fossero un unico file. Generalmente archiviare dei file non significa necessariamente comprimerli, anche se questa è una possibilità. Alcuni esempi d'uso possono essere:
tar cvf ciao.tar /home
# crea un tar della directory "/home" tar cvf ciao.tar file1 file2 file3
# crea un tar con
# all'interno i tre file tar cvf mydirectory.tgz .
# crea un archivio della directory
# corrente tar tvf ciao.tar
# elenca il contenuto dell'archivio tar tar -tf <file.tar.gz> | xargs rm -r
# elimina tutti i file che
# sono stati estratti dall'archivio menzionato, è molto comodo
# quando ci troviamo davanti a tarbomb, cioè pacchetti che non
# presentano al loro interno una parent directory ma un insieme
# esagerato di file tar xvf ciao.tar
# estrae in loco il contenuto dell'archivio
# tar tar xvpf ciao.tar
# estrae in loco il contenuto dell'archivio
# tar, il flag "-p", serve a preservare i permessi dei file
# all'interno dell'archivio tar xvpf ciao.tar --xattrs
# estrae in loco il contenuto
# dell'archivio tar, il flag "-p", serve a preservare i permessi
# dei file all'interno dell'archivio e l'opzione "--xattrs" serve
# a preservare gli attributi dei file all'interno dell'archivio tar xvf ciao.tar -C /percorso/preferito
# estra il contenuto di
# un file tar nella directory /percorso/preferito tar caf target.tar.xz file1 file2 file3
# con il flag -a indica
# di utilizzare lo schema di compressione indicato nel suffisso
# dell'archivio, molto comodo, quindi ad esempio se avessimo
# usato come suffisso ".tar.gz" avrebbe utilizzato gzipUn altro flag molto utilizzato è 'p', per mantenere gli stessi permessi all'interno dell'archivio, così nel momento di una futura estrazione la gerarchia di permessi sui file non va persa. Nel caso volessimo comprimere, abbiamo diverse opzioni in funzione dell'algoritmo di compressione che preferiamo utilizzare, generalmente abbiamo:
gzip or gunzip
# per comprimere con questo algoritmo ci basta
# includere il flag -z alle opzioni precedenti passate al tar, ad
# esempio "tar cvzf ciao.tar.gz /home" bzip2
# per comprimere con questo algoritmo ci basta includere
# il flag -j ai comandi tar "tar cvjf ciao.tar.bz2 /home"Ad ogni modo è bene tenere in mente che archiviazione e compressione possono lavorare sepratamente, ad esempio:
gzip nomeFile.tar
# comprime l'archivio nomeFile.tar gzip -1 nomeFile.tar
# comprime l'archivio utilizzando un
# algoritmo più veloce, avremo però meno compressione ( il valore
# numerico può andare da 1 a 9 gunzip nomeFileCompresso.tar.gz
# decomprime il file
# nomeFileCompresso.tar.gzpossiamo utilizzare gunzip anche per decomprimere dati nel formato
zlib o deflate (che comunque usa zlib) che sono comunemente
utilizzati nel protocollo HTTP eseguendo:
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - pcap_21_extracted_body | gunzip bzip2 nomeFile.tar
# comprime il file nomeFile.tar bunzip2 nomeFile.tar.bz2
# decomprime il file nomeFile.tar.bz2Nota Bene: Esistono delle analogie tra le estensioni dei file archiviati e compressi:
| Suffisso Breve | Suffisso Lungo |
|---|---|
| .tgz | .tar.gz |
| .tbz, .tbz2, .tb2 | .tar.bz2 |
| .taz, .tz | .tar.Z |
| .tlz | .tar.lz, .tar.lzma |
| .txz | .tar.xz |
Vediamo ora alcuni esempi di tar in cui viene combinata la compressione/decompressione:
tar zxvf ciao.tar.gz
# decomprime ed estrae l'archivio
# compresso con gunzip tar jxvf ciao.tar.bz2
# decomprime ed estrae l'archivio
# compresso con bzip2 tar tzf nomeArchivio.tar.gz
# visualizza il contenuto di un
# archivio compresso con gunzip tar Jxvf ciao.tar.xz
# decomprime ed estrae l'archivio
# compresso con xzN.B.: Bzip è un algoritmo più lento ma è molto efficiente quando usato per comprimere file di testo, quindi viene utilizzato per distribuire codice sorgente. Un'altro algoritmo che sta sempre diventando più famoso è "xz" e il suo corrispettivo "unxz". Per decomprimere invece archivi di tipo rar, possiamo usare unrar, ed eseguire "unrar l nomearchivio.rar" per visualizzarne il contenuto e "unrar x nomearchivio.rar" per estrarre l'archivio.
Esistono generalmente due tipi di librerie:
- Shared libraries are .so (or in Windows .dll, or in OS X .dylib) files. All the code relating to the library is in this file, and it is referenced by programs using it at run-time. A program using a shared library only makes reference to the code that it uses in the shared library.
- Static libraries are .a (or in Windows .lib) files. All the code relating to the library is in this file, and it is directly linked into the program at compile time. A program using a static library takes copies of the code that it uses from the static library and makes it part of the program. [Windows also has .lib files which are used to reference .dll files, but they act the same way as the first one].
There are advantages and disadvantages in each method.
- Shared libraries reduce the amount of code that is duplicated in each program that makes use of the library, keeping the binaries small. It also allows you to replace the shared object with one that is functionally equivalent, but may have added performance benefits without needing to recompile the program that makes use of it. Shared libraries will, however have a small additional cost for the execution of the functions as well as a run-time loading cost as all the symbols in the library need to be connected to the things they use. Additionally, shared libraries can be loaded into an application at run-time, which is the general mechanism for implementing binary plug-in systems.
- Static libraries increase the overall size of the binary, but it means that you don't need to carry along a copy of the library that is being used. As the code is connected at compile time there are not any additional run-time loading costs. The code is simply there.
Personally, one could prefer shared libraries, but use static libraries when needing to ensure that the binary does not have many external dependencies that may be difficult to meet, such as specific versions of the C++ standard library or specific versions of the Boost C++ library.
Detta in modo pragmatico le librerie sono file che contengono pezzi di codice a cui i programmatori fanno riferimento all'interno dei loro programmi, anche perchè la riscrittura di quel pezzo di codice o l'inclusione della librearia stessa all'interno del loro programma, costerebbe loro spazio aggiuntivo. Un file di libreria normalmente ha estensione ".so" o ".a".
Per poter visualizzare di quali librerie fa uso un determinato programma possiamo utilizzare:
ldd percorsoDelProgramma
# dove il percorso del programma può
# essere individuato con whereis nomeProgrammaInoltre per permettere ad un programma di precaricare una determinata libreria prima di tutte le altre possiamo utilizzare la variabile d'ambiente LD_PRELOAD, ad esempio:
LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so skype
# in questo caso
# aggiungiamo una libreria da far caricare ad un software
# chiamato skype prima di tutte le altreEsistono diversi modi per configurare le librerie di sistema su GNU/Linux:
- Configurazione Globale (o Global Configurations): configurazione valida per tutti gli utenti di un sistema
- Configurazione locale o d'ambiente (Environment Configurations): configurazione valida per un utente specifico
Quando cambiamo una qualche configurazione riguardante le librerie, dobbiamo effettuare una pulizia della cache, questo avviene per rendere effettivi i cambiamenti, a questo proposito viene usato il comando:
ldconfig
# ricarica le librerie disponibili ldconfig -v
# visualizza le librerie attualmente caricate dal
# sistemaA volte un determinato software cerca una specifica libreria e non la trova, nel caso dovessimo avere sul sistema una libreria molto simile, magari che differisce di una sola o poche versioni da quella cercata si può risolvere il problema, andando ad effettuare dei link di questa libreria esistente utilizzando i nomi delle librerie cercate. Il file contenente la configurazione globale di sistema delle librerie è "/etc/ld.so.conf"; in questo file, troveremo una direttiva di include che ci dirà dove è localizzata la directory che contiene i file contenenti i percorsi a alle librerie. Nella directory "/etc/ld.so.conf.d/" sono invece contenuti diversi file con estensione ".conf" che contengono i veri e propri percorsi alle librerie. La directory contenente le librerie di sistema è costituita da "/lib".
Nel caso volessimo avere una libreria privata, che può quindi vedere solo il mio utente (per questioni di privacy, o per effettuare dei test) la soluzione migliore è creare una directory che contiene questa/queste libreria/e e poi creare una variabile d'ambiente che mi fornisce il link alla directory contenente la mia libreria. Ad esempio:
mkdir /usr/local/mylibrarycreo una directory e all'interno ci metto la mia libreriaexport LD_LIBRARY_PATH=/usr/local/mylibrarymodifico la variabile d'ambienteLD_LIBRARY_PATHcontenente il percorso alle librerie accessibile all'utente
N.B.: possiamo anche utilizzare più percorsi, infatti utente posso utilizzare il separatore ":" per indicare i vari percorsi, come ad esempio:
export LD_LIBRARY_PATH=/usr/local/mylibrary:/usr/local/mylibrary2Ricorda che se sono state effettuate delle modifiche all'interno del file /etc/ld.so.conf, allora dobbiamo lanciare un "ldconfig", viceversa se abbiamo aggiunto delle librerie solo per il mio utente allora non sarà necessario lanciare il comando "ldconfig". In linea di massima possiamo dire che:
- In presenza di modifiche della Configurazione Globale -> necessario un "ldconfig"
- In presenza di modifiche della Configurazione Locale -> non necessario un "ldconfig"
Talvolta pur essendoci la libreria richiesta, prendiamo ad
esempio la libreria "libXft.so.2", il lancio di un eseguibile
potrebbe ancora lanciare il messaggio "error while loading shared
libraries: libXft.so.2: cannot open shared object file: No such
file or directory", questo avviene in quanto il sistema vuole
quella specifica libreria, ma per un'altra architettura, nel
nostro caso potrebbe ad esempio volere la versione per
architettura "i386" di quella libreria, mentre noi abbiamo solo
la versione per architettura x86_64, dobbiamo quindi procedere
con l'aggiungere i pacchetti per l'architettura "i386" e
installare la libreria. SOlitamente su Debian una determinata
libreria o pacchetto per un'altra architettura si può installare
accodando al nome del pacchetto la stringa ":i386", quindi nel
nostro caso, se la libreria "libXft.so.2" appartiene al pacchetto
"libxft2" ci basterà eseguire:
# sudo apt-get install libxft2:i386Il programma "dd" costituisce un comando molto flessibile che ci permette di copiare o convertire file da una locazione ad uno specifico file, viene usato per diversi scopi, alcuni esempi applicativi sono:
- Creare immagini ISO
- Effettuare Backup
- Salvare i primi 512 Byte nella partizione "/" di root per
- salvare il Master Boot Record
- Per riempire di zeri una partizione o in genere un dispositivo di memoria per poterlo svuotare completamente di tutti i dati presenti
- Per creare in genere un file di una determinata dimensione (ad esempio per effettuare qualche tipo di simulazione)
- Per creare file di swap
- Effettuare benchmark grossolani
- Salvare un dispositivo con tutte le sue relative partizioni e tabella delle partizioni, se ad esempio c'è un HD con diversi sistemi operativi e diversi dati, o ad esempio un'immagine SD di un sistema operativo con una configurazione particolare, possiamo usare dd per copiare tutto
Esempi di utilizzo sono:
dd if=/root/mydir of=/home/user/backup.iso
# dove if sta per "
# input file" e of sta per "output file", in questo esempio viene
# creata un'immagine iso della directory "mydir" dd if=/dev/sda1 of=/home/user/mbr.iso bs=512 count=1
# in
# questo caso viene effettuato un backup del Master Boot Record,
# che costituisce i primi 512 byte della partizione/dev/sda1-
Il flag "bs" indica la dimensione del blocco (block size), ad esempio anche opzioni come "bs=1M" o "bs=2G" sono valide, dove i suffissi M e G indicano corrispettivamente Megabyte e Gigabyte, non utilizzare un suffisso corrisponde quindi ad una dimensione in byte, di default se il block size non viene specificato la dimensione è fissata a 512 byte
-
Il flag "count" indica quanti blocchi della dimensione del flag bs devono essere copiati, in questo caso, siccome ci interessano solo i primi 512 byte, il flag count è settato ad 1, mentre nel caso avessimo messo "count=2" allora in tutto avremmo copiato 1024 byte
-
N.B.: Posso capire qual'è la mia partizione di boot, effettuando un "df -h" e visualizzando qual'è il device su cui è montata la partizione "/"
dd if=/dev/urandom of=a.log bs=1M count=2
# genera un file di
# 2MB con contenuto casualeAltri esempi di utilizzo possono essere:
dd if=/dev/zero of=/home/user/zero bs=1M count=1
# crea un file
# da 1MB di dimensione, riempendolo di zeri... Quest'operazione
# poteva essere effettuata anche attraverso i flag bs=1024
# count=1024 dd if=/dev/zero of=/dev/sdb1
# cancella tutti i dati sulla
# partizione sdb1 riempendola di zeri dd if=/dev/zero of=/dev/null bs=1M count=32768
# effettua un
# benchmark sulla banda di operazione CPU/Memoria, andando a
# leggere qualche GB di zeri e poi buttandoli via, il risultato
# sarà in B/s, più è alto e più il sistema è efficienteper poter visualizzare un feedback sulla percentuale di completamento possiamo eseguire:
sudo pkill -USR1 -n -x dd
# manda un segnale al programma dd,
# quest'ultimo risponderà con la quantità di dati copiatiun'alternativa a dd che riporta anche informazioni sullo stato e percentuale di completamento è "dcfldd".
Nota che a volte quando cerchiamo di creare chiavette USB con immagini di alcuni sistemi operativi, e.g., slackware, gentoo, freebsd, è preferibile, prima di dare queste immagini in pasto a " dd" di eseguire un:
isohybrid nome_immagine.iso
# rende un iso ibrida in modo da
# poter essere leggibile sia da un sistema UEFI che ISO.Vediamo ora alcuni comandi per la manipolazione di file.
Un programma molto utile per eseguire uno specifico comando per ogni voce sullo standard output è xargs, vediamone un esempio applicativo:
ls | grep test | xargs rm
# rimuove tutti i file elencati, cioè
# tutti i file che hanno la parola "test" all'interno del loro
# nomexargs in pratica quindi prende come input una lista di linee ed esegue un comando per ogni linea.
E' importante ricordare che esiste su diversi sistemi operativi il limite dei 128K con messaggio di error "Agument list too long", questo errore e' comune quando con delle wildcards matchano un grosso numero di file, quando questo accade dobbiamo utilizzare xargs e find o printf.
Esempio:
printf '%s\0' finalplain* | xargs -0 rmUn altro esempio:
printf '%s\0' /usr/include/sys/*.h | \
xargs -0 grep foo /dev/nullVediamo un altro esempio:
echo 'one two three' | xargs mkdirPer vedere quali comandi vengono effettivamente eseguiti possiamo fare cosi':
echo 'one two three' | xargs -t rm
# l'opzione -t ci mostra i comandi che vengono eseguitiUn'opzione piu' sicura rispetto a -t che puo' essere utilizzata sia per visualizzare il comando eseguito ma anche per chiedere conferma all'utente e':
echo 'onw two three' | xargs -p rmConsiglio sempre di utilizzare l'opzione -p a meno che non stiamo scrivendo uno script in cui non vogliamo chiedere conferma attraverso un input dell'utente.
Vediamo un altro esempio, ipotizziamo di avere un file di stringhe e vogliamo convertire ognuna di queste stringhe in base64, per farlo possiamo usare xargs in questo modo:
cat file.txt | xargs -p -n1 -I{} sh -c 'echo {} | base64'Il programma xargs e' spesso usato in combinazione col programma find, ricorda che infatti nonostante find abbia un'opzione chiamata '-exec', in realta' e' molto piu' efficiente in termini di tempo utilizzare xargs.
Sort è un programma utilizzato per riordinare i risultati sullo standard output
ls -al | sort -n -k5
# this will sort the stdout numerically
# attraverso il flag "-n" in funzione della quinta colonna,
# attraverso il flag "-k5" in quanto il risultato di un "ls -al"
# fornisce come quinta colonna le dimensioni dei file, le colonne
# sono separate da uno spazio di default sort -n -k5 test.txt
# stampa sullo standard output il file
# test.txt riordinato numericamente in funzione della quinta
# colonna sort -k7 -r test.txt > test_new.txt
# riordina in modalità
# inversa, attraverso il flag "-r", in funzione della settima
# colonna il file test.txt e salva il risultato nel file "
# test_new.txt" sort -t"," -k1,3 test.txt
# in questo caso viene usato come
# separatore il carattere "," attraverso il flag "-t" e il
# riordinamento avviene in funzione della colonna 1 e della
# colonna 3 sul file chiamato "test.txt"Possiamo anche specificare il separatore ad esempio, se settato su un tab per un file tsv ad esempio, possiamo riordinare il file in funzione della seconda colonna numerica in ordine decrescente facendo:
sort -t$'\t' -nr -k2Oppure possiamo ad esempio ordinare i file in cui il delimiter per le colonne e' il '|' con:
sort -t$'|' -nr -k2La maggior parte delle volte vogliamo avere solo le linee uniche per fare questo possiamo utilizzare:
sort -u test.txt
# visualizza il file escludendo le linee ripetuteVediamo altri esempi di utilizzo di sort:
sort a b | uniq > c # c is a union b
sort a b | uniq -d > c # c is a intersect b
sort a b b | uniq -u > c # c is set difference a - bQuesti due comandi vengono utilizzati solitamente per sostituire uno o una serie di spazi in un file con dei tab o viceversa, o ad esempio cambiare il numero di spazi da cui è composto un tab. Vediamo un esempio:
expand myfile.txt > myfile2.txt
# questo converte i caratteri
# tab in spazi expand --tabs=10 myfile.txt > myfile2.txt
# espando a 10 spazi
# tutti i tab del file myfile.txt e salvo il risultato nel file
# myfile2.txt unexpand -a myfile.txt > myfile2.txt
# converto tutti gli spazi
# in tab e salvo risultati in myfile2.txtPaste è un programma che unisce le righe di due file, ma è molto utilizzato per unire colonne da file diversi oppure per visualizzare le differenze tra due file, in quanto sullo standard output i due file vengono affiancati; un esempio applicativo è:
paste test1 test2
# stampa riga per riga i due file sullo
# standard output, molto utile nel momento in cui dobbiamo
# confrontare i due file paste -d: users.txt passwords.txt
# in questo caso genereremo
# un file con le righe accoppiate e separate dal simbolo ":"Possiamo anche visualizzare un file con tutti i valori su una colonna sulle righe (quindi conversione colonna -> riga) eseguendo:
paste -s users.txt
# -s serve per convertire colonna in riga nello stesso filePossiamo anche decidere il delimiter utilizzando:
paste -sd',' users.txt
# in questo caso -d',' imposta come delimiter per ogni campo
# della riga il carattere virgola ','Possiamo anche mettere piu' elementi delle colonne nella stessa riga, ad esempio:
paste - - - - < input.txt
# in questo caso stiamo riorganizzando la struttura del file input.txt
# con 4 colonne dove ogni elemento e' preso consecutivamente dal
# file in inputPossiamo anche riorganizzare la struttura del file separando le colonne con un punto e virgola ';' e mettendo tre colonne per ogni riga:
paste -d';' - - - < inputNota che lo stesso identico risultato puo' essere ottenuto eseguendo:
paste -sd ';;\n'
# dove il numero di caratteri delimitatori determina la struttura del file
# quindi in questo caso avremmo un elemento ; un elemento ; un elemento
# e poi nuova rigaIl comando "tr" viene utilizzato per effettuare sostituzioni carattere per carattere, ad esempio:
tr blah test < file.txt
# questo comando "tradurrà" e cioè
# sostituerà all'interno del file file.txt il catattere "b" col
# carattere "t", il carattere "l" col carattere "e", il carattere
# "a" col carattere "s" e il carattere "h" col carattere "t" tr a-z A-Z < fileName
# converte un testo in minuscolo in un
# testo in maiuscolo tr -d 'a-zA-Z' < fileName
# col flag -d rimuoviamo tutti i
# caratteri menzionati tr -dc 'a-zA-Z' < fileName
# col flag -c facciamo il
# complemento del set dei caratteri menzionati, quindi in questo
# caso con -dc in pratica eliminiamo tutti i caratteri dal file,
# eccetto quelli nel gruppo 'a-zA-Z'Possiamo utilizzare il comando tr anche per effettuare squeeze, cioe' ad esempio rimuovere ripetizioni di caratteri. Un esempio e' voler rimuovere le doppie spaziature all'interno di un file, questo puo' essere fatto eseguendo:
tr -s ' ' < filenameUn altro utilizzo e' quello di rimuovere caratteri specifici da un file come ad esempio, nel caso volessimo rimuovere tutti i newline possiamo eseguire:
tr -d '\n' < filenameInoltre per indicare i set di caratteri possiamo anche utilizzare notazioni del tipo [[:alnum:]] o [[:alpha:]] e cosi' via.
N.B.: Per effettuare la sostituzione di stringhe il comando sed è più flessibile.
Per contare le linee esistono diverse opzioni, alcune classiche opzioni sono:
nl file.txt
# stampa il numero di linee del file chiamato
# file.txt nl -s. file.txt
# stampa il numero di linee del file menzionato
# inoltre accoda ad ogni numero un ".", il flag "-s" serve
# appunto a mettere una stringa dopo il numero di linea cat -n file.txt
# stampa il numero di linee del file chiamato
# file.txtNel caso avessimo un file con righe ridondanti e vogliamo mostrare solo le righe uniche, quindi senza contare le righe ridondanti, utilizziamo il comando "uniq", ad esempio:
cat file.txt | sort | uniq -u
# oppure possiamo utilizzare "sort -u"E' possibile formattare il testo attraverso il comando "fmt", per vedere le diverse opzioni possiamo effettuare un "man fmt".
Un applicazione utile di fmt ad esempio e' quando non siamo stati troppo attenti nel formattare il nostro file o script ignorando il numero di colonne massimo per mantenere una certa leggibilita'.
Ad esempio, per molti linguaggi di programmazione la convenzione e' avere un massimo di 80 colonne per ogni riga.
Il comando fmt ci aiuta nel fare questo, ad esempio, nel caso il nostro script chiamato "script.c" non rispettasse la convenzione delle 80 colonne possiamo fixarlo eseguendo:
fmt -w 80 script.cDi default, il comando fmt, formatta utilizzando 75 caratteri per riga, quindi e' equivalente ad un -w 75.
Questo comando è utile per visualizzare le righe uniche all'interno di un file, deve essere usato sempre in coppia con " sort" altrimenti considera unica una riga solo se non è uguale alla precedente, vediamo qualche esempio di utilizzo
cat data.txt | sort | uniq -c
# mostra per ogni riga quante
# occorrenze ci sono cat data.txt | sort | uniq -u
# mostra solo le righe uniche cat data.txt | sort | uniq | sort -n
# mostra per ogni riga
# quante occorrenze ci sono ma questa volte secondo un ordine
# crescente, quindi le righe più rare saranno in altoIn informatica con il termine backup, copia di sicurezza o copia di riserva si indica la replicazione, su un qualunque supporto di memorizzazione, di materiale informativo archiviato nella memoria di massa dei computer al fine di prevenire la perdita definitiva dei dati in caso di eventi malevoli accidentali o intenzionali. Si tratta dunque di una misura di ridondanza fisica dei dati, tipica delle procedure di disaster recovery. [Wikipedia]
Nei sistemi GNU/Linux Esistono diverse tecniche per effettuare backup, è da notare che in realtà esistono diverse tipologie di backup, ad esempio il metodo più semplice di backup sarebbe quello di effettuare una semplice copia attraverso il comando "cp" , con:
cp -u mioFile mioFile2
# in questo caso il file viene copiato
# solo nel caso in cui mioFile2 non esiste o nel caso in cui
# mioFile2 esistente è più vecchio, ma non avviene una
# sincronizzazione completa (cioè nel caso di intere directory i
# file eliminati nella directory sorgente rimangono nella
# directory destinataria se sono stati copiati in un altro
# momento precedente)L'esempio visto qui sopra è veramente basilare e non fa altro che effettuare una semplice copia, mentre i programmi di backup generalmente possono presentare le seguenti funzionalità:
- Copia immagine di un disco rigido
- Copia selettiva di directory e singoli file
- Criteri di selezione per la ricerca dei contenuti salvati e per la scelta di quelli che devono essere oggetto di backup (per data, tipo di file, autore della modifica)
- Compressione dei contenuti per ridurre la memoria richiesta per la copia
- Sicurezza: protezione dei dati copiati attraverso password e crittografia
Vediamo ora alcune tecniche per effettuare backup su sistemi GNU/Linux che prevedono l'utilizzo di Tar o Rsync.
Un semplice modo di effettuare backup col comando Tar ed ottenere compressione è:
tar -pczf mybackup.tar.gz /home/user/
# viene effettuato un
# backup della directory /home/user/ in un archivio chiamato
# mybackup.tar.gz, il flag "-p" indica di preservare la struttura
# dei permessi di tutti i file e il flag "-z" di comprimere
# utilizzando l'algoritmo gzipUn altro esempio molto interessante è quello di effettuare backup periodici utilizzando questa il programma tar, questo è possibile attraverso uno script in cui scriviamo:
tar -pczf /home/backup/backup.`/bin/date +\%y\%m\%d`.tar.gz home/user/
# crea archivi con la data nel nome, della directory /home/userUn'altra opzione è quella di aggiungere questo comando a "cron", in modo da poterlo eseguire periodicamente.
Uno strumento veramente molto flessibile per effettuare backup è costituito da "rsync", molte distro hanno questo comando installato di default. Vediamo subito alcuni esempi:
rsync -av sourceDir /var/backups/destDir
# copia la directory
# sourceDir in destDir e lo fa in modalità "verbose" cioè
# stampando sullo standard output file per file copiato, il flag "
# -a" sta per archivio e costituisce la combinazione di più flag "
# -rlp" e quindi:
# 1.copia ricorsivamente le directory
# 2.copia anche i link
# 3.preserva la struttura dei permessi rsync -avz --delete /media/sorgente /media/giuseppe/destinazione/
# viene effettuata una copia di
# backup da sorgente a destinazione, il flag "-z", indica di
# effettuare la compressione per il trasferimento, e l'opzione "
# --delete" cancella i file in "destinazione" che non sono
# presenti in "sorgente", quindi "destinazione" diventa una copia
# esatta di "sorgente" rsync -avzi --delete --progress /media/sorgente /media/giuseppe/destinazione/
# viene effettuata la stessa
# operazione precedente, solo che attraverso il flag "-i" vengono
# visualizzate le modifiche effettuate in destinazione e
# attraverso l'opzione "--progress" viene visualizzato lo stato
# del backupIl programma rsync può anche essere usato per sincronizzare directory su (o da) server remoti, ad esempio:
rsync -av gng@andromeda:/home/gng/mySourceFolder /home/marco/BackupServer/Possiamo anche utilizzare una porta diversa dalla 22 attraverso un lancio leggermente piu' arzigogolato come:
rsync -avzh --delete -e "ssh -p 2222" output/ user@1.1.1.1:/srv/www/website/
# sincronizziamo da locale a remoto
# utilizzando la porta 2222 rsync -avzh --delete -e "ssh -p 2222" user@1.1.1.1:/srv/www/website/ output/
# sincronizziamo da remoto a locale
# utilizzando la porta 2222Per poter visualizzare file di testo compressi possiamo utilizzare le utility: zcat, zless, zmore e zgrep.
For binary files, use hd, hexdump or xxd for simple hex dumps and bvi, hexedit or biew for binary editing.