Quelle est la difference entre ls [13] et ls {1,3}?

11

J'ai créé trois fichiers dans mon répertoire à l'aide de la commande touch inv{1..3}.txt. Maintenant, j'ai utilisé deux commandes et leur sortie est à peu près la même. Ces deux commandes sont ls inv[13].txtet ls {1,3}.txt.

Alors, comment ces deux sont-ils différents? En quoi les crochets sont-ils différents des accolades? Je cherchais également "linux [..]", mais je n'ai rien trouvé, alors pourrais-je savoir comment ces choses sont appelées dans la terminologie linux?

Merci

posixKing
la source
2
Le nom de ceci est "extension de nom de fichier" ou "globbing".
Byte Commander
Lequel de ces éléments est l'expansion ou la globalisation de nom de fichier? Est-ce le support carré ([..]) ou le support de fleurs ({..})?
posixKing du

Réponses:

14
  • {}est appelé expansion de l'accolade. Il a deux formes: {x..y}et {x,y}, remplacez xet ypar n'importe quelle valeur alphabétique ou numérique.

    Dans le premier formulaire, {x..y}sera étendu à toutes les valeurs de xà y, inclus. Par exemple, {2..5}sera étendu à 2, 3, 4, 5.

    Dans la seconde forme explicite, {x,y}sera étendu seulement x, y. Par exemple, {2,5}sera étendu à 2et 5.

    Si aucune expansion n'est possible, le motif est traité littéralement, par exemple dans {a..3}.

    Une chose importante à noter est que l'expansion de l'accolade sera effectuée (si possible) indépendamment de toute correspondance de fichier, lors de la création / correspondance de fichiers.

  • []est connu comme un modèle d'expansion (ou globbing) de chemin d'accès. Contrairement à l'expansion d'accolade, vous ne pouvez l'utiliser que lors de la correspondance des noms de fichiers, elle sera traitée littéralement si vous l'utilisez lors de la création de fichiers.

    Il a deux formes: [xyz...]et [x-y].

    Dans le premier formulaire, il correspondra à tout caractère unique à l'intérieur des crochets séparément, c'est-à-dire que chaque caractère est traité individuellement. Ainsi, [25].txtil correspondra à un fichier nommé 2.txtou 5.txtdans le répertoire en cours, tandis [245].txtqu'il correspondra à n'importe quel fichier nommé 2.txtou 4.txtou 5.txt.

    Dans la deuxième forme, une extension de plage est effectuée avant de correspondre individuellement, si possible sinon traitée littéralement. Donc, pour [2-5]. txt, il correspondra à tout fichier nommé 2.txtou 3.txtou 4.txtou 5.txt. Si la plage ne peut pas être étendue, elle sera traitée littéralement, par exemple en cas de [a-3].txt.


Une différence de comportement importante entre ces deux éléments réside dans le fait qu'il y a plus de modèles à mettre en correspondance alors que moins en fait ils correspondent. Comme l'expansion de l'accolade est effectuée, quoi qu'il en soit, cela montrera l'erreur que certains fichiers n'existent pas tandis que l'expansion du nom de chemin correspondra autant que possible sans aucune erreur pour le reste:

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

Remarque sur la portabilité:

L' []opérateur d'expansion de nom de chemin est défini par POSIX, donc portable entre le shell Bourne et ses dérivés.

L'expansion d'accolade,, {}n'est pas définie par POSIX et n'est donc pas portable entre tous les shells. Par exemple, dash( shdans Ubuntu) n'a pas cela. Il a été emprunté à cshet travailler sur certaines coquilles seulement par exemple bash, zsh, ksh93, fish. Assurez-vous que le shell que vous utilisez prend en charge cela avant de l'implémenter.


Exemple:

$ touch {1..3}.txt

$ ls {1..3}.txt
1.txt  2.txt  3.txt

$ ls {1,2,3}.txt
1.txt  2.txt  3.txt

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls {a..3}.txt
ls: cannot access {a..3}.txt: No such file or directory

$ ls [123].txt
1.txt  2.txt  3.txt

$ ls [1-3].txt
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

$ ls [a-3].txt
ls: cannot access [a-3].txt: No such file or directory
heemayl
la source
1
Il faut éviter de se fier au comportement d' [ ]expansion lorsqu'il n'y a pas de correspondance car cela peut être différent selon la configuration du shell. Si vous souhaitez utiliser [ou ]dans un nom de fichier, il doit être cité dans vos commandes. Il convient également de noter la différence entre {13..79}et [13-79]. La première produira tous les nombres dans la plage de 13à 79, la seconde correspondra aux personnages 1, 3, 4, 5, 6, 7et 9.
kasperd
@kasperd Oui, c'est pour ça nullglob(ou similaire). À propos de l' [13-79]appariement, je pense que j'ai mentionné clairement dans ma réponse le comportement par caractère de [] '.
heemayl
@heemayl Je pense qu'il vaut également la peine de mentionner que la forme `{1..3}` est du bashisme. Cela ne fonctionnera pas dans le tiret. Je pense kshavoir cette fonctionnalité, mais pas ses saveurs plus modernes, comme mksh et pkdsh
Sergiy Kolodyazhnyy
@Serg Ajout de la note de portabilité.
heemayl
7

La principale différence entre les deux formes est illustrée ici:

$ ls inv[15].txt
inv1.txt
$ ls inv{1,5}.txt
ls: cannot access 'inv5.txt': No such file or directory
inv1.txt

inv[15].txtest un glob et étendra la liste des fichiers correspondants sur votre système de fichiers. Il s'agit d'une extension de nom de chemin .

inv{1,5}.txtse développe inv1.txtet inv5.txtquels que soient les fichiers qui se trouvent réellement sur votre système de fichiers. C'est l' expansion de l'accolade .

John1024
la source
L'autre différence clé est que vous pouvez écrire ba{con,tman}et qu'il n'y a pas d'équivalent en utilisant des crochets. IOW, l'expansion d'accolade n'est pas seulement pour les personnages uniques.
Hobbs