Jak wyświetlić listę plików bez katalogów i filtrować według nazwy (opcje ls)

42

Mam katalog o nazwie uploads. Zawiera kilka plików oraz kilka podkatalogów, które z kolei zawierają pliki.

Czy istnieje sposób (w jednym kroku) na wykonanie następujących czynności:

  1. Wymień TYLKO pliki w katalogu głównym przesyłania - nie chcę widzieć nazw podfolderów ani ich zawartości;

    i

  2. NIE wymieniaj żadnych plików, które zaczynają się od t_

Wiem o -dfladze, ale nie zapewnia mi to, czego chcę.

EmmyS
źródło

Odpowiedzi:

53

To brzmi jak praca find.

  • Służy -maxdepthdo zwracania tylko bieżącego katalogu, a nie rekurencyjnego przeszukiwania podfolderów
  • Służy -type fdo zwracania tylko plików, a nie katalogów, węzłów urządzeń lub czegokolwiek innego
  • Użyj kombinacji, jeśli -noti -nameaby uniknąć plików o nazwach, których nie chcesz

Może to wyglądać tak:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Caleb
źródło
Dzięki! Jestem całkiem nowy w CLI i nigdy wcześniej nie korzystałem z find. Na pewno przyjrzę się temu.
EmmyS,
2
@EmmyS: Możesz tu znaleźć jeszcze jedną sztuczkę. @Gilles wspomniał o użyciu -exec ls -lG -- {} +w swojej odpowiedzi, aby uzyskać wynik przy użyciu dodatkowych opcji dla ls. Możesz także dodać tylko -lsdo tego znaleziska, aby uzyskać szybkie i brudne przybliżenie szczegółowego widoku ls.
Caleb
18

GNU ls (tj. Polecenie ls w niewbudowanych systemach Linux i Cygwin, dostępne również w niektórych innych systemach unikatowych) ma opcję ukrywania niektórych plików na podstawie ich nazw. Nie można jednak zignorować katalogów.

ls --hide='t_*' uploads

Innym podejściem jest sprawienie, aby powłoka dopasowała się. Bash, ksh i zsh mają wzorzec negacji !(t_*)pasujący do wszystkich plików oprócz pasujących t*; w bash ta funkcja musi być włączona za pomocą shopt -s extglob, aw zsh musi być włączona za pomocą setopt ksh_glob. Zsh ma również równoważną składnię, ^t_*którą należy włączyć setopt extended_glob. To nadal nie ignoruje katalogów. Zsh ma dodatkową funkcję, która pozwala dopasowywać pliki nie tylko według nazwy, ale także według metadanych i innych: kwalifikatorów glob . Dodaj (.)na końcu dopasowania, aby ograniczyć się do zwykłych plików. Negacja ^jest częścią składni dopasowania nazwy, więc ^t_*(.)oznacza „wszystkie zwykłe pliki nie pasują t_*”, a nie „wszystkie pliki, które nie są zwykłymi plikami pasujące t_*”.

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Jeśli znajdziesz się bez zaawansowanych narzędzi, możesz to zrobić na dowolnym Uniksie find. To nie jest coś, co zwykle wpisujesz w wierszu poleceń, ale jest mocne i precyzyjne. Caleb już pokazał, jak to zrobić za pomocą GNU find . Ta -maxdepthopcja nie jest przenośna; -prunezamiast tego możesz użyć , aby przenośnie przestać się findpowtarzać.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Zamień -printna, -exec ls -lG -- {} +aby wykonać lsz ulubionymi opcjami plików.

Wszystkie powyższe polecenia ukrywają pliki kropkowe (tzn. Pliki, których nazwa zaczyna się na a .). Jeśli chcesz je wyświetlić, należy przekazać -Ado lslub dodać Dkwalifikator glob w zsh ( ls uploads/^t_*(.D)). Za pomocą findmożna zastosować inne podejście, aby rekursja była powtarzana tylko o jeden poziom ( findnie traktuje specjalnie plików kropek). Działa to findw pełni tylko wtedy, gdy uruchomisz w bieżącym katalogu.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Gilles „SO- przestań być zły”
źródło
3
Czy masz dzienną robotę? ;-) Ciągle jestem zdumiony długością i poziomem szczegółowości twoich odpowiedzi, nawet na najprostsze pytania tutaj w Unix SE! .. Tak trzymaj! :)
alex
Dzięki! Dobry szczegół. Nie wiem, czy mam teraz „zaawansowane narzędzia”, czy nie; Jestem na komputerze Mac w pracy (chociaż Linux w domu, więc jestem pewien, że w pewnym momencie się przyda).
EmmyS
@EmmyS: W przypadku twojego linuksa mój sposób użycia -maxdepthpowinien działać, ale problem „przenośności”, o którym wspomina Gilles, polega na tym, że BSD find(myślę, że także w OSX) jest nieco innym zwierzęciem, więc możesz potrzebować jego odpowiedzi. @Gilles: +1 za sztuczkę zsh!
Caleb
1
@Gilles: Przyszły mi do głowy niektóre niezbyt soczyste komentarze na temat prunes, ale odpuszczę, mówiąc po prostu, że kiedy chowam się na własnych systemach, tyle razy myśl „ czy to polecenie zadziała, gdybym był włączony AIX, Solaris lub MINIX3 ”jest w przybliżeniu ... w trybie gotowości ... Mam trudności z odczytaniem licznika ... wyświetlacz jest zamrożony 0.00.
Caleb
2
Czy Gnu nie lsma --use-telepathyopcji? To najszybszy sposób, aby wyświetlić tylko te pliki, które chcesz. Może jednak nie być przenośny.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
źródło
Co jest $9w tym stwierdzeniu?
EmmyS,
3
@ EmmyS Oznacza 9. pole / kolumnę wyniku. Ta odpowiedź próbuje przeanalizować lsdane wyjściowe .
jw013,
print $ NF` byłby lepszy, IMO. $ NF oznacza liczbę pól, która wynosiłaby 9 i jest powszechnym zastosowaniem w AWK jako dobra okazja do nauczenia innych o $ NF.
Elijah Lynn,
1
ls -l | grep -v ^d | grep name$
RICARDO MARMOLEJO GARCIA
źródło
Co sprawiłoby, że to rozwiązanie (wymagające wielu poleceń i potoków) byłoby lepsze find?
HalosGhost
Jest zwięzły, łatwy do odczytania i pozostaje zgodny z konwencją poleceń ls. Łatwiej jest mi zapamiętać niż argumenty polecenia find. Do każdego własnego i uznania dla opcji!
tkjef
0

Pozwól, że spróbuję za pomocą lsi rur:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

powiedzmy, że ostatnia kolumna jest dziewiąta.

Y0NG
źródło
1
Co jeśli są pliki ze spacjami?
jordanm
0

Jeśli problem z przenośnością find -maxdepth stanowi problem, możesz użyć:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Nie jestem ekspertem, ale myślę, że to powinno zadziałać. Przypuszczam, że wygląda to trochę tajemniczo, ale jeśli mówisz awk, to tak naprawdę nie jest. Zamiast 9 USD można użyć $ NF. Możesz także:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

co robi to samo (ale być może mniej wydajnie niż poprzednie ???).

Właściwie, po przemyśleniu innych postów, wygląda na to

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

jest jeszcze krótszym i bardziej przejrzystym sposobem.

Niech ktoś mnie poprawi, jeśli się mylę. :-)

kkaszub
źródło
Parsowanie nie lsjest na ogół dobrym pomysłem . Twoje sztuczki z awk zakończą się niepowodzeniem, na przykład z nazwami plików z białymi spacjami.
Mat.
@mat - Dziękujemy za korektę. Po przeczytaniu artykułu, który wskazałeś (i jw013), widzę, że nie można ufać, że ls wyśle prawidłowe nazwy plików. Nawet jeśli miałbym przepisać kod awk, aby wydrukować wszystko od 9 $ do końca wiersza (w tym białe znaki), to wyjście ls może nadal być błędne. Jest to rozczarowujące i powinno zostać poprawione przez IMO. Dzięki jeszcze raz.
kkaszub
0

Znalazłem te krótkie sposoby:

ls -p uploads | grep -Ev '/'

lub

ls -pIt_* uploads | grep -v /
Radu Rădeanu
źródło
-1

Wypróbuj ten alias i użyj go:

alias l='ls -hLlF'
Ziarnisty
źródło
ls -hLlFpokazuje podkatalogi i pokazuje pliki zaczynające się od t_. Jak to odpowiada na pytanie?
Raphael Ahrens,
Być może źle zrozumiałem pytanie. ls -hLlF nie pokaże docelowych katalogów połączonych katalogów.
Granulowany
Na to wygląda. Ale czy nie przeczytałeś innych odpowiedzi na pytanie?
Raphael Ahrens
-1

Bułka z masłem:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

Koparka
źródło
(1) Ta odpowiedź jest tak łatwa, że ​​została podana wcześniej. (2) Dlaczego uważasz, że musisz podać pełną ścieżkę do katalogu?
Scott
@Scott - jest to bardzo szybki i prosty sposób na znalezienie rozwiązania. Podano pełną ścieżkę, aby odpowiedź była uniwersalna ...
Digger