Elenco con `ls` ed espressione regolare


15

Come posso elencare i file con un nome file che termina con l'ultimo carattere e con l' .txtestensione?

Ho provato ls *+([[:digit:]]).txtma questo è vero per abc12.txte abc2.txt.

Ma devo solo ottenere abc2.txt. Come posso fare ciò?

C'è qualche forma :digit:che lo farà?


2
Modello Va notato è valida solo con il globbing esteso endabled: shopt -s extglob.
donothings successo

Risposte:


20

Che ne dite di:

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

L' !inizio del gruppo completa il suo significato.

Come notato nei commenti, questo è bash, prova ad esempio:

printf "%s\n" *[!0-9][0-9].txt

3
Nota che bash (ie ls) non supporta le espressioni regolari qui. Queste sono espressioni di nome file (Globbing) . Puoi vedere la differenza già nel tuo esempio: qui *c'è un carattere jolly, che non è presente nelle espressioni regolari, dove useresti .*per ottenere lo stesso. Le espressioni regolari sono molto più potenti del globbing.
Christopher K.

2

La domanda chiedeva espressioni regolari. Bash, e quindi ls, non supporta le espressioni regolari qui. Ciò che supporta sono le espressioni del nome file ( Globbing ), una forma di caratteri jolly. Le espressioni regolari sono molto più potenti di così.

Se vuoi davvero usare le espressioni regolari, puoi usare find -regexcosì:

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

Trova è ricorsivo per impostazione predefinita, ma lsnon lo è. Per trovare solo i file nella directory corrente, è possibile disabilitare la ricorsione con -maxdepth 1. Trova corrispondenze con il nome file con percorso, ecco perché i nomi dei file iniziano con ./se esegui find in .. La regex inizia \./con questo. Nota che in una regex .c'è un personaggio speciale che si adatta a qualsiasi personaggio, ma qui vogliamo davvero un punto, ecco perché lo sfuggiamo con una barra rovesciata. Facciamo lo stesso per il punto in .txt, perché altrimenti anche la regex corrisponderebbe Atxt. Le classi di cifre sono le stesse del globbing, solo che è necessario ^invece di !invertire la classe di caratteri.

Se vuoi ottenere l'output di ls, puoi usare in -exec lsquesto modo:

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

findsupporta un paio di diversi sapori regex. È possibile specificare un -regextype, ad esempio:

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

Per me, i tipi possibili sono: 'findutils-default', 'awk', 'egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic' , 'posix-egrep', 'posix-extended', 'posix-minimal-basic', 'sed' Puoi correre find -regextype helpper scoprire cosa è supportato sul tuo sistema.


0

Con i globs estesi ksh (o bash -O extglobo zsh -o kshglob) che stai già utilizzando, sarebbe:

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

O

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

Se si desidera abbinare a1.txt e,2.txt ma non, a12.txt12.txt.

Tuttavia nota che in ksh e bash (a meno che tu non imposti l' failglobopzione per ottenere un comportamento simile a quello di zsh), se quel modello non corrisponde a nessun file, il modello verrà passato letteralmente a ls, e se quel file (dal nome strano) succede a esiste, verrà elencato lsanche se non corrisponde al modello stesso.

Per includere .2.txt, imposta l' dotglobopzione in bash, aggiungi il (D)qualificatore glob in zshoppure imposta FIGNOREsu !(.|..)in ksh93.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.