web-dev-qa-db-fra.com

Que signifient les caractères génériques à double astérisque?

J'ai essayé la commande suivante mais j'ai du mal à l'interpréter:

ls **

mais je ne sais pas exactement ce qu'il produit et pourquoi c'est le résultat.

48
Mike Blair

Il utilise probablement une fonction spéciale de certains shells qui permet à ** faire une correspondance récursive, par opposition à une seule *, qui ne correspond que dans le répertoire courant.

Le caractère générique * correspond à n'importe quel fichier ou répertoire (dont le nom ne commence pas par .) dans le répertoire courant.

Selon le Shell que vous utilisez et avec quels paramètres, ** peut être équivalent à *; il peut correspondre à zéro ou plusieurs caractères suivis de zéro ou plusieurs caractères, ce qui revient à ne faire correspondre qu'une seule fois zéro ou plusieurs caractères.

Mais avec certains obus, avec certains paramètres, ** est une version récursive de *, correspondant à tous les fichiers et répertoires du répertoire et des sous-répertoires actuels.

Citant le bash manual :

`* '
Correspond à n'importe quelle chaîne, y compris la chaîne nulle. Lorsque l'option Shell "globstar" est activée et que "*" est utilisé dans un contexte d'extension de nom de fichier, deux "*" adjacents utilisés comme modèle unique correspondront à tous les fichiers et à zéro ou plusieurs répertoires et sous-répertoires. S'ils sont suivis d'un `/ ', deux` `*' 'adjacents correspondront uniquement aux répertoires et sous-répertoires.

Cela ne fonctionne que si l'option globstar est définie via:

shopt -s globstar

(il est désactivé par défaut) et uniquement dans les versions relativement récentes de bash.

Je crois que zsh prend également en charge cette syntaxe.

Il est important de garder à l'esprit que les caractères génériques sont développés par le shell, et non par la commande ls. Si vous tapez ls **, ou ls *.txt, la commande ls elle-même ne voit jamais le * personnages; il ne voit qu'une liste étendue de fichiers, comme si vous aviez tapé la liste entière sur la ligne de commande.

117
Keith Thompson

Le comportement exact de ce caractère générique particulier a été bien couvert par les autres réponses, mais des informations sur le cas général peuvent être utiles.

Ce comportement n'est pas limité à ls et est appelé "globbing", qui est l'expansion de modèles basés sur des correspondances avec des noms de fichiers existants. Il est important de noter que ces modèles n'utilisent pas de syntaxe d'expression régulière.

Le shell pré-traite les arguments avant de les envoyer au programme. Il existe généralement plusieurs niveaux d'expansion, dont certains impliquent la globulation.

La page de manuel unix est une excellente ressource pour plus d'informations sur les autres caractères génériques disponibles dans un modèle de fichier glob. Une version en ligne de glob peut être trouvée ici .

Enfin, un exemple simple de ce que cela peut faire pour vous, en particulier lorsqu'il est combiné avec d'autres goodies d'extension Shell, dans ce cas, ceux fournis par le shell bash. Des informations sur les extensions utilisées dans cet exemple peuvent être trouvées dans le Bash Guide for Beginners - qui est ma ressource goto, malgré le titre.

ls *{01..04}.{txt,csv} devient ls *01.txt *01.csv *02.txt *02.csv *03.txt *03.csv *04.txt *04.csv

Ce qui pourrait produire quelque chose comme ceci:

input_01.txt input_02.txt input_03.txt input_04.txt output_01.csv output_02.csv output_03.csv output_04.csv

En sautant ces derniers:

input_05.txt input_06.txt input_07.txt input_08.txt input_09.txt input_10.txt output_05.csv output_06.csv output_07.csv output_08.csv output_09.csv output_10.csv

Un exemple trivial, mais si vous savez que ce comportement n'est pas spécifique à ls, alors vous pouvez imaginer l'utilitaire lorsqu'il est couplé à mv, cp, rsync, etc.

6
Morgen

Semblable à la commande DOS dir, la fonction de la commande ls est de répertorier les fichiers et les répertoires. Lorsque la chose à répertorier est un fichier, la commande répertorie simplement le fichier, ce n'est pas grave. Lorsque l'élément à répertorier est un dossier, la commande répertorie le conten du dossier. De plus, si vous venez de la commande ls sans arguments, la chose par défaut à lister est le répertoire de travail, ou le dossier courant. (De plus, le nom du dossier actuel est toujours ., donc la commande nue ls est équivalente à ls ..)

Exemple: vous avez dans votre dossier actuel un fichier nommé file_001, un dossier nommé folder_002, et dans le dossier, vous avez des fichiers nommés picture_003 et picture_004. Lorsque vous tapez ls, vous verrez file_001 folder_002, et lorsque vous tapez ls folder_002, tu verras picture_003 picture_004.

Sous Unix, le traitement des caractères génériques est effectué par le shell. Lorsque vous tapez ls **, votre Shell traite le **, avant d'exécuter la commande ls, il remplace la commande ** avec les noms de tous les fichiers/dossiers correspondants. (Le * le caractère générique correspond à n'importe quel fichier ou dossier. En utilisant ** correspond à tout fichier ou dossier dont le nom commence par n'importe quoi et se termine par quoi que ce soit, il est donc fonctionnellement équivalent à juste *.)

Dans ce cas, lorsque la commande ls est exécutée, les arguments de la ligne de commande sont une liste de tous les fichiers et dossiers du dossier actuel, comme si vous les aviez tous tapés vous-même. Donc, dans notre exemple, vous exécutez maintenant la commande ls file_001 folder_002. Lorsque la commande ls traite sa ligne de commande, le premier élément est un fichier, il répertorie simplement le fichier et le deuxième élément est un dossier, il répertorie donc le contenu du dossier. De plus, comme la commande répertorie plusieurs éléments, elle imprime une étiquette avec le nom du dossier, de sorte que vous pouvez différencier le contenu du dossier dans la liste de sortie de tout ce qui est également répertorié. Par conséquent, la sortie de la commande ls ** ressemblera à ceci:

file_001

folder_002:
picture_003   picture_004`

Je suis curieux cependant. Quel guide, livre ou document vous a suggéré d'essayer la commande ls **?

1