Listing z `ls` i wyrażeniem regularnym

15

Jak mogę wyświetlić listę plików o nazwie kończącej się ostatnim znakiem i .txtrozszerzeniem?

Próbowałem, ls *+([[:digit:]]).txtale dotyczy to abc12.txti abc2.txt.

Ale muszę tylko dostać abc2.txt. Jak mogę to zrobić?

Czy istnieje jakaś forma :digit:tego umożliwiająca?

Web-E
źródło
2
Należy zauważyć, wzór jest ważny tylko z przedłużony masek endabled: shopt -s extglob.
donotings udane

Odpowiedzi:

20

Co powiesz na:

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

!Na początku grupy uzupełnia swoje znaczenie.

Jak zauważono w komentarzach, robi to bash, spróbuj np .:

printf "%s\n" *[!0-9][0-9].txt
Thor
źródło
3
Zauważ, że bash (tj. ls) Nie obsługuje tutaj wyrażeń regularnych. Są to wyrażenia nazw plików (Globbing) . Różnicę widać już w przykładzie: tutaj *znajduje się symbol wieloznaczny, którego nie ma w wyrażeniach regularnych, w których można by .*to osiągnąć. Wyrażenia regularne są o wiele potężniejsze niż globowanie.
Christopher K.
2

Pytanie zadane dla wyrażeń regularnych. Bash lsnie obsługuje tutaj wyrażeń regularnych. Obsługuje wyrażenia nazw plików ( Globbing ), formę symboli wieloznacznych. Wyrażenia regularne są o wiele potężniejsze.

Jeśli naprawdę chcesz używać wyrażeń regularnych, możesz użyć find -regextego w następujący sposób:

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

Znajdź jest domyślnie rekurencyjne, ale lsnie jest. Aby znaleźć tylko pliki w bieżącym katalogu, możesz wyłączyć rekursję za pomocą -maxdepth 1. Znajdź dopasowania do nazwy pliku ze ścieżką, dlatego nazwy plików zaczynają się, ./jeśli uruchomisz find .. Wyrażenie regularne zaczyna się \./od poradzenia sobie z tym. Zauważ, że w wyrażeniu regularnym .jest to znak specjalny pasujący do dowolnej postaci, ale tutaj naprawdę chcemy kropki, dlatego uciekamy od niej odwrotnym ukośnikiem. Robimy to samo dla kropki .txt, ponieważ w przeciwnym razie wyrażenie regularne również by pasowało Atxt. Klasy cyfr są takie same jak dla globowania, tyle, że trzeba ^zamiast !odwrócić klasę znaków.

Jeśli chcesz uzyskać wynik ls, możesz użyć w -exec lsnastępujący sposób:

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

findobsługuje kilka różnych smaków wyrażeń regularnych. Możesz określić -regextypena przykład:

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

Dla mnie możliwe są następujące typy: „findutils-default”, „awk”, „egrep”, „ed”, „emacs”, „gnu-awk”, „grep”, „posix-awk”, „posix-basic” , „posix-egrep”, „posix-Extended”, „posix-minimal-basic”, „sed” Możesz uruchomić, find -regextype helpaby dowiedzieć się, co jest obsługiwane w twoim systemie.

Christopher K.
źródło
0

Z rozszerzonymi globami ksh (lub bash -O extgloblub zsh -o kshglob), których już używasz, byłyby to:

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

Lub

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

Jeśli chcesz dopasować na a1.txt a2.txt , ale nie a12.txtani 12.txt.

Pamiętaj jednak, że w ksh i bash (chyba że ustawisz failglobopcję uzyskania zachowania podobnego do zachowania zsh), jeśli ten wzorzec nie pasuje do żadnego pliku, wzorzec zostanie przekazany dosłownie ls, a jeśli ten (dziwnie nazwany) plik zdarzy się istnieje, zostanie wyświetlony na liście, lsnawet jeśli nie pasuje do samego wzorca.

Aby włączyć .2.txt, należy ustawić dotglobopcję bash, dodać (D)kwalifikator glob w zshlub ustaw FIGNOREsię !(.|..)w ksh93.

Stéphane Chazelas
źródło