Vous risquez de perdre des données en utilisant ce caractère générique Linux de manière incorrecte
Les caractères génériques de Linux vous permettent de saisir une seule commande qui agit sur des groupes entiers de fichiers en même temps. Cela permet de gagner beaucoup de temps, à moins que les choses tournent mal. Et c'est possible. De manière destructive.
Sommaire
À quoi servent les caractères génériques
Les caractères génériques les plus connus sont le point d'interrogation, ?, et l'astérisque, *. Ils peuvent être utilisés pour créer des modèles de noms de fichiers. Le point d'interrogation représente n'importe quel caractère unique et l'astérisque représente n'importe quelle séquence de caractères, y compris les caractères zéro.
Sachant cela, nous pouvons construire des modèles qui correspondent à plusieurs noms de fichiers. Au lieu de saisir tous les noms de fichiers sur la ligne de commande, nous saisissons le modèle à la place. Tous les fichiers qui correspondent au modèle sont traités par la commande.
Si nous avons une collection de fichiers dans un répertoire comme celui-ci :
Nous pouvons sélectionner des groupes de fichiers qui correspondent aux modèles que nous fournissons.
ls taf_*
Cela nous donne tous les fichiers avec « taf_ » au début de leur nom.
ls *.sh
ls s*.sh
La première commande répertorie tous les fichiers de script shell du répertoire. La deuxième commande répertorie uniquement les fichiers commençant par « s » qui sont également des fichiers de script shell.
Tout cela semble assez simple, et avec ls, ça l'est. Mais d'autres commandes peuvent utiliser ce type de recherche de motifs. Des problèmes surviennent lorsque le shell essaie d'aider en faisant une recherche de motifs avant que la commande n'ait eu l'occasion de le faire.
Utilisation de l'astérisque avec la commande find
L'action consistant à développer un modèle dans une liste de fichiers correspondants est appelée globuleux.
Il s'agissait au départ d'une commande autonome dans la version 6 d'Unix, puis elle est devenue une bibliothèque pouvant être liée à d'autres programmes, et aujourd'hui, il s'agit d'une commande intégrée au shell. L'extension du modèle est effectuée par le shell, et les résultats de l'extension sont transmis à la commande sous forme de paramètres de ligne de commande.
Nous allons examiner deux exemples utilisant la commande find. L'un fait ce à quoi vous vous attendez, mais le second pourrait bien vous surprendre.
Pour cet exemple, nous allons utiliser un répertoire contenant un seul fichier, appelé readme.txt. Il y a deux répertoires, src et inc. Ils contiennent un mélange de fichiers C, H, MD et TMP.
ls -R
Nous pouvons utiliser find pour rechercher de manière récursive des fichiers (-type f) avec des noms qui correspondent à notre modèle (-name *.c), nous donnant une liste des fichiers C.
find . -type f -name *.c
Nous pouvons ajouter l'option -not pour inverser la recherche, en nous montrant tout en dehors de les fichiers C.
find . -type f -not -name *.c
Après avoir examiné cette liste, nous choisissons de tout supprimer sauf les fichiers C. Nous pouvons le faire en ajoutant l'option -delete.
find . -type f -not -name *.c -delete
find .
La deuxième commande find répertorie de manière récursive tout ce qui se trouve dans et sous le répertoire actuel. Il ne reste que nos fichiers C.
Cela a fonctionné comme la plupart d'entre nous l'auraient attendu. Nous allons maintenant faire exactement la même chose, mais cette fois, le fichier dans le répertoire actuel n'est pas un fichier texte, c'est un fichier C.
ls -R
Nous utiliserons la même commande find et les mêmes options pour supprimer tout sauf les fichiers C. Ce n'est pas du tout ce que nous voulions.
find . -type f -not -name *.c -delete
find .
Cela a supprimé allègrement chaque fichier de l'arborescence du répertoire, à l'exception du fichier C du répertoire actuel.
Nous allons réinitialiser les fichiers une fois de plus et émettre la commande de la manière dont nous sommes censé pour l'utiliser.
Tous les fichiers sont en place et nous avons un fichier C dans le répertoire courant, comme nous l’avions fait auparavant.
ls -R
Cette fois, nous allons envelopper le modèle générique dans des guillemets simples.
find . -type f -not -name '*.c' -delete
find .
C'est ce que nous voulions. Tout a disparu, à part nos fichiers C.
OK, alors qu'est-ce qui s'est passé ?
Les guillemets simples empêchent le shell de développer le modèle de nom de fichier. Il est transmis tel quel à la commande ou au programme, pour que la commande agisse dessus.
Dans l'exemple qui a fonctionné, nous avions un fichier readme.txt dans le répertoire courant. Le shell n'a pas pu trouver de correspondance avec *.c, il a donc passé *.c à find pour agir dessus.
Dans l'exemple qui a supprimé tout sauf les fichiers C, nous avions un fichier appelé main.c dans le répertoire courant. Le shell a fait correspondre le modèle à ce fichier et a transmis le nom du fichier à la commande find. Les instructions de find étaient donc de supprimer tout ce qui n'était pas appelé main.c.
Nous pouvons illustrer cela avec un petit programme C qui ne fait rien de plus qu’afficher ses paramètres de ligne de commande dans la fenêtre du terminal.
#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 printf("%-2d) "%s"n", i, argv(i));
exit (0);
}
Je l'ai enregistré sous un fichier appelé glob.c et je l'ai compilé avec :
gcc -o glob glob.c
La variable argc contient le nombre d'arguments que nous passons au programme. Une boucle for parcourt la liste des arguments et imprime chacun d'eux dans la fenêtre du terminal.
La boucle for démarre à l'argument un, pas à zéro. Il y a un argument zéro. Il contient toujours le nom du binaire lui-même. Pour éviter de brouiller les pistes, j'ai évité de l'imprimer. Les seuls arguments qui sont imprimés sont ceux que nous fournissons sur la ligne de commande.
./glob one two 3 ant beetle cockroach
Essayons cela avec *.c comme paramètre de ligne de commande.
ls *.c
./glob *.c
Sans aucun fichier C dans le répertoire courant, le shell transmet *.c à la commande find. La commande find agit alors sur le modèle générique lui-même. Mais, lorsque nous avons un fichier C dans le répertoire courant, le shell transmet le nom du fichier C correspondant au programme.
ls *.c
./glob *.c
Notre programme reçoit le nom du fichier C comme paramètre, et il en est de même pour la commande find. En fait, find faisait ce qu'on lui demandait de faire : supprimer tous les fichiers à l'exception du fichier main.c.
Cette fois, nous allons envelopper le modèle générique dans des guillemets simples.
ls *.c./glob '*.c'
Le shell ignore la possibilité d'appliquer son globbing au modèle générique et le transmet directement à la commande pour un traitement ultérieur.
Une solution simple, vous pouvez me citer
En règle générale, indiquez les modèles génériques que vous transmettez à des commandes telles que find. C'est tout ce qu'il faut pour éviter ce type d'incident potentiellement désastreux.