Liste avec `ls` et expression régulière

15

Comment répertorier les fichiers dont le nom se termine par le dernier caractère et l' .txtextension?

J'ai essayé ls *+([[:digit:]]).txtmais c'est vrai pour abc12.txtet abc2.txt.

Mais je dois seulement obtenir abc2.txt. Comment puis je faire ça?

Y a-t-il une sorte de forme :digit:qui fera cela?

Web-E
la source
2
Il convient de noter modèle est uniquement valable étendue englobement endabled: shopt -s extglob.
donothingsuccess

Réponses:

20

Que diriez-vous:

ls *[!0-9][0-9].txt

Le !début du groupe complète son sens.

Comme indiqué dans les commentaires, c'est la tâche de bash, essayez par exemple:

printf "%s\n" *[!0-9][0-9].txt
Thor
la source
3
Notez que bash (ie ls) ne prend pas en charge les expressions régulières ici. Ce sont des expressions de nom de fichier (Globbing) . Vous pouvez déjà voir la différence dans votre exemple: ici, *est un caractère générique, qui n'est pas là dans les expressions régulières, où vous utiliseriez .*pour obtenir la même chose. Les expressions régulières sont beaucoup plus puissantes que la globalisation.
Christopher K.
2

La question demandait des expressions régulières. Bash, et donc ls, ne prend pas en charge les expressions régulières ici. Il prend en charge les expressions de nom de fichier ( Globbing ), une forme de caractères génériques. Les expressions régulières sont beaucoup plus puissantes que cela.

Si vous voulez vraiment utiliser des expressions régulières, vous pouvez utiliser find -regexcomme ceci:

find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt'

La recherche est récursive par défaut, mais lsne l'est pas. Pour rechercher uniquement des fichiers dans le répertoire en cours, vous pouvez désactiver la récursivité avec -maxdepth 1. Trouver des correspondances avec le nom de fichier avec chemin d'accès, c'est pourquoi les noms de fichiers commencent par ./si vous exécutez find in .. Le regex commence par \./faire face à cela. Notez que dans une expression régulière, .est un caractère spécial correspondant à n'importe quel caractère, mais ici, nous voulons vraiment un point, c'est pourquoi nous l'échappons avec une barre oblique inverse. Nous faisons la même chose pour le point dedans .txt, car autrement l'expression régulière correspondrait également Atxt. Les classes de chiffres sont les mêmes que pour la globalisation, juste ce dont vous avez besoin ^au lieu d' !inverser la classe de caractères.

Si vous voulez obtenir la sortie de ls, vous pouvez utiliser -exec lscomme ceci:

 find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt' -exec ls -lah {} \;

findprend en charge plusieurs saveurs regex différentes. Vous pouvez spécifier un -regextype, par exemple:

find . -maxdepth 1 -regextype egrep -regex '\./.*[^0-9][0-9]\.txt'

Pour moi, les types possibles sont: 'findutils-default', 'awk', 'egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic' , 'posix-egrep', 'posix-extended', 'posix-minimal-basic', 'sed' Vous pouvez exécuter find -regextype helppour découvrir ce qui est pris en charge sur votre système.

Christopher K.
la source
0

Avec les globs étendus ksh (ou bash -O extglobou zsh -o kshglob) que vous utilisez déjà, ce serait:

ls -d -- ?(*[![:digit:]])[[:digit:]].txt

Ou

ls -d -- !(*[[:digit:]])[[:digit:]].txt

Si vous voulez faire correspondre sur a1.txt et2.txt mais pas sur a12.txtni 12.txt.

Cependant, notez que dans ksh et bash (sauf si vous définissez l' failgloboption pour obtenir un comportement similaire à celui de zsh), si ce modèle ne correspond à aucun fichier, le modèle sera transmis littéralement à ls, et si ce fichier (étrangement nommé) arrive à existe, il sera répertorié par lsmême s'il ne correspond pas au modèle lui-même.

Pour inclure .2.txt, réglez l' dotgloboption bash, ajouter le (D)qualificatif de glob dans zshou ensemble FIGNOREà !(.|..)en ksh93.

Stéphane Chazelas
la source