Stai rischiando la perdita di dati utilizzando questo carattere jolly Linux sbagliato
I caratteri jolly Linux ti consentono di digitare un singolo comando che agisce su interi gruppi di file contemporaneamente. È un grande risparmio di tempo, a meno che le cose non vadano male. E possono. Distruttivamente.
A cosa servono i caratteri jolly
I caratteri jolly più conosciuti sono il punto interrogativo, ?, e l'asterisco, *. Questi possono essere utilizzati per creare modelli di nomi di file. Il punto interrogativo rappresenta qualsiasi singolo carattere e l'asterisco rappresenta qualsiasi sequenza di caratteri, inclusi zero caratteri.
Sapendo questo, possiamo costruire modelli che corrispondono a più nomi di file. Invece di digitare tutti i nomi dei file sulla riga di comando, digitiamo invece il pattern. Tutti i file che corrispondono al modello vengono gestiti dal comando.
Se abbiamo una raccolta di file in una directory come questa:
Possiamo selezionare gruppi di file che corrispondono ai modelli che forniamo.
ls taf_*
Questo ci dà tutti i file con "taf_" all'inizio del nome.
ls *.sh
ls s*.sh
Il primo comando elenca tutti i file di script della shell nella directory. Il secondo comando elenca solo i file che iniziano con "s" che sono anche file di script di shell.
Sembra tutto abbastanza semplice e con ls lo è. Ma altri comandi possono utilizzare questo tipo di corrispondenza dei modelli. I problemi sorgono quando la shell tenta di aiutare con la corrispondenza dei modelli prima che il comando abbia una possibilità.
Utilizzando l'asterisco con il comando find
L'azione di espandere un modello in un elenco di file corrispondenti è chiamata globbing.
È iniziato come comando autonomo nella versione 6 di Unix, poi è diventato una libreria che poteva essere collegata ad altri programmi e oggigiorno è integrato nella shell. L'espansione del modello viene eseguita dalla shell e i risultati dell'espansione vengono passati al comando come parametri della riga di comando.
Esamineremo due esempi utilizzando il comando find. Uno fa quello che ti aspetteresti, ma il secondo potrebbe sorprenderti.
Per questo esempio, utilizzeremo una directory con un singolo file al suo interno, chiamato readme.txt. Ci sono due directory, src e inc. Contengono un mix di file C, H, MD e TMP.
ls -R
Possiamo usare find per trovare ricorsivamente file (-type f) con nomi che corrispondono al nostro pattern (-name *.c), fornendoci un elenco dei file C.
find . -type f -name *.c
Possiamo aggiungere l'opzione -not per invertire la ricerca, mostrandoci tutto tranne i file C.
find . -type f -not -name *.c
Dopo aver esaminato questo elenco, scegliamo di eliminare tutto tranne i file C. Possiamo farlo aggiungendo l'opzione -delete.
find . -type f -not -name *.c -delete
find .
Il secondo comando find elenca ricorsivamente tutto dentro e sotto la directory corrente. Tutto ciò che rimane sono i nostri file C.
Ha funzionato come la maggior parte di noi si sarebbe aspettata. Ora faremo esattamente la stessa cosa, ma questa volta il file nella directory corrente non è un file di testo, è un file C.
ls -R
Utilizzeremo lo stesso comando e le stesse opzioni di ricerca per eliminare tutto tranne i file C. Non è affatto quello che volevamo.
find . -type f -not -name *.c -delete
find .
Questo ha cancellato allegramente ogni singolo file nell'albero delle directory, a parte un file C nella directory corrente.
Reimposteremo i file ancora una volta ed eseguiremo il comando nel modo in cui dovremmo usarlo.
Tutti i file sono a posto e abbiamo un file C nella directory corrente, proprio come facevamo prima.
ls -R
Questa volta racchiuderemo il pattern dei caratteri jolly tra virgolette singole.
find . -type f -not -name '*.c' -delete
find .
Questo è ciò che volevamo. Tutto è andato a parte, a parte i nostri file C.
OK, quindi cosa è andato storto?
Le virgolette singole impediscono alla shell di espandere il modello del nome file. Viene passato al comando o al programma così com'è, affinché il comando possa agire su di esso.
Nell'esempio che ha funzionato, avevamo un file readme.txt nella directory corrente. La shell non è riuscita a trovare una corrispondenza con *.c, quindi ha passato *.c per trovare su cui agire.
Nell'esempio in cui abbiamo eliminato tutto tranne i file C, nella directory corrente avevamo un file chiamato main.c. La shell ha abbinato il modello a quel file e ha passato il nome del file al comando find. Quindi le istruzioni di find erano di eliminare tutto ciò che non si chiamava main.c.
Possiamo illustrarlo con un piccolo programma C che non fa altro che visualizzare i parametri della riga di comando nella finestra del terminale.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
printf("You supplied %d arguments.\n", argc-1);
for (i=1; i<argc; i++)
printf("%-2d) \"%s\"\n", i, argv[i]);
exit (0);
}
L'ho salvato come file chiamato glob.c e l'ho compilato con:
gcc -o glob glob.c
La variabile argc contiene il numero di argomenti che passiamo al programma. Un ciclo for scorre l'elenco degli argomenti e li stampa ciascuno nella finestra del terminale.
Il ciclo for inizia dall'argomento uno, non da zero. C'è un argomento zero. Contiene sempre il nome del file binario stesso. Per evitare di intorbidire l’acqua, ho evitato di stamparlo. Gli unici argomenti che vengono stampati sono quelli che forniamo sulla riga di comando.
./glob one two 3 ant beetle cockroach
Proviamolo con *.c come parametro della riga di comando.
ls *.c
./glob *.c
Senza file C nella directory corrente, la shell passa *.c al comando find. Il comando find agisce quindi sul modello di caratteri jolly stesso. Ma, quando abbiamo un file C nella directory corrente, la shell passa al programma il nome del file C corrispondente.
ls *.c
./glob *.c
Il nostro programma riceve come parametro il nome del file C e lo stesso vale per il comando find. Quindi in realtà find stava facendo ciò che gli era stato detto di fare: eliminare tutti i file tranne il file main.c.
Questa volta racchiuderemo il pattern dei caratteri jolly tra virgolette singole.
ls *.c
./glob '*.c'
La shell ignora la possibilità di applicare il globbing al modello di caratteri jolly e lo passa direttamente al comando per un'ulteriore elaborazione.
Una soluzione semplice, puoi citarmi
Come regola generale, cita i modelli di caratteri jolly che stai passando a comandi come find. Questo è tutto ciò che serve per prevenire questo tipo di incidente potenzialmente disastroso.