Listado con `ls` y expresión regular

15

¿Cómo puedo enumerar archivos con un nombre de archivo que termina con el último carácter y con .txtextensión?

Lo he intentado ls *+([[:digit:]]).txtpero esto es cierto para abc12.txty abc2.txt.

Pero solo necesito llegar abc2.txt. ¿Cómo puedo hacer eso?

¿Hay alguna forma de :digit:hacer eso?

Nosotros somos
fuente
2
Patrón Cabe señalar sólo es válida con englobamiento extendido endabled: shopt -s extglob.
donothings exitosamente

Respuestas:

20

Qué tal si:

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

El !principio del grupo complementa su significado.

Como se señaló en los comentarios, esto es bash, intente, por ejemplo:

printf "%s\n" *[!0-9][0-9].txt
Thor
fuente
3
Tenga en cuenta que bash (es decir ls) no admite expresiones regulares aquí. Estas son expresiones de nombre de archivo (Globbing) . Puede ver la diferencia ya en su ejemplo: aquí, *hay un comodín, que no está allí en las expresiones regulares, donde usaría .*para lograr lo mismo. Las expresiones regulares son mucho más poderosas que el globbing.
Christopher K.
2

La pregunta pedía expresiones regulares. Bash, y por lo tanto ls, no admite expresiones regulares aquí. Lo que admite son expresiones de nombre de archivo ( Globbing ), una forma de comodines. Las expresiones regulares son mucho más poderosas que eso.

Si realmente quieres usar expresiones regulares, puedes usar find -regexasí:

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

Buscar es recursivo por defecto, pero lsno lo es. Para buscar solo archivos en el directorio actual, puede deshabilitar la recursividad con -maxdepth 1. Encuentra coincidencias con el nombre del archivo con la ruta, por eso los nombres de los archivos comienzan ./si ejecutas find in .. La expresión regular comienza con \./hacer frente a eso. Tenga en cuenta que en una expresión regular, .es un carácter especial que coincide con cualquier carácter, pero aquí realmente queremos un punto, por eso nos escapamos con una barra invertida. Hacemos lo mismo para el punto .txt, porque la expresión regular también coincidiría Atxt. Las clases de dígitos son las mismas que para globbing, solo que necesita en ^lugar de !invertir la clase de caracteres.

Si desea obtener la salida de ls, entonces puede usar -exec lsasí:

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

findadmite un par de diferentes sabores de expresiones regulares. Puede especificar un -regextype, por ejemplo:

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

Para mí, los tipos posibles son: 'findutils-default', 'awk', 'egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic' , 'posix-egrep', 'posix-extended', 'posix-minimal-basic', 'sed' Puede ejecutar find -regextype helppara averiguar qué es compatible con su sistema.

Christopher K.
fuente
0

Con el ksh extendió pegotes (o bash -O extglobo zsh -o kshglob) que ya está usando, que sería:

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

O

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

Si quieres hacer coincidir a1.txt y2.txt no pero a12.txttampoco 12.txt.

Sin embargo, tenga en cuenta que en ksh y bash (a menos que configure la failglobopción de obtener un comportamiento similar al de zsh), si ese patrón no coincide con ningún archivo, el patrón se pasará literalmente als , y si ese archivo (con un nombre extraño) sucede existe, aparecerá en la lista lsaunque no coincida con el patrón en sí.

Para incluir .2.txt, establezca la dotglobopción de bash, añadir el (D)calificativo pegote en zsh, o conjunto FIGNOREde !(.|..)en ksh93.

Stéphane Chazelas
fuente