Wyświetlaj tylko zwykłe pliki (ale nie katalogi) w bieżącym katalogu

126

Mogę użyć, ls -ld */aby wyświetlić listę wszystkich pozycji katalogu w bieżącym katalogu. Czy istnieje podobnie prosty sposób, aby po prostu wyświetlić listę wszystkich zwykłych plików w bieżącym katalogu? Wiem, że mogę użyć find

find . -maxdepth 1 -type f

lub stat

stat -c "%F %n" * | grep "regular file" | cut -d' ' -f 3-

ale nie wydają mi się zbyt eleganckie. Czy istnieje przyjemny, krótki sposób, aby wyświetlić tylko zwykłe pliki (nie dbam o urządzenia, potoki itp.), Ale nie podkatalogi bieżącego katalogu? Lista linków symbolicznych również byłaby plusem, ale nie jest koniecznością.

Daniel Kullmann
źródło
5
Co rozumiesz przez „zbyt elegancki”? O ile wiem, findpolecenie jest najlepszym sposobem na robienie tego, co chcesz. Aby uzyskać pewne niezawodne inne opcje, powinieneś przyjrzeć się poleceniom specyficznym dla powłoki (a te nie są przenośne)!
rahmu
@rahmu Byłem za czymś podobnym ls -d */, co jest krótkie, łatwe do pisania i łatwe do zrozumienia. Jestem więc bardzo zadowolony z odpowiedzi Ulricha Dangela, mimo że nie używam zsh.
Daniel Kullmann

Odpowiedzi:

32

Za pomocą zshi Glob Qualifiers możesz łatwo wyrazić to bezpośrednio, np .:

echo *(.)

zwróci tylko listę zwykłych plików lub błąd w zależności od konfiguracji.

W przypadku katalogów innych niż katalogi:

echo *(^/)

(będzie zawierać dowiązania symboliczne (w tym do katalogów), nazwane potoki, urządzenia, gniazda, drzwi ...)

echo *(-.)

dla zwykłych plików i dowiązań symbolicznych do zwykłych plików.

echo *(-^/)

dla nie-katalogów i bez dowiązań symbolicznych do katalogów.

Zobacz także Dkwalifikator globbing, jeśli chcesz dołączyć pliki D ot (pliki ukryte), takie jak *(D-.).

Ulrich Dangel
źródło
170
ls -p | grep -v / 

To polecenie wyświetla listę wszystkich nie ukrytych plików, które nie są katalogami (zwykłe pliki, łącza, pliki urządzeń itp.). Aby dołączyć także ukryte pliki, dodaj -Aopcję dols

Zakłada, że ​​żaden z plików nie ma w nazwie znaków nowej linii. Dodanie -qopcji lsprzekształciłoby wszystkie niedrukowalne znaki, w tym znak nowej linii ?, gwarantując, że znajdują się one w jednej linii, i dlatego są odpowiednie do podawania do narzędzia opartego na linii, takiego jak grepi do drukowania na terminalu.

Athul Biju
źródło
14
+1, to dobra odpowiedź. Głosowanie w dół nad nowym użytkownikiem bez komentarza jest dla mnie dość szokujące, zwłaszcza gdy podano roboczą odpowiedź. Jedyny przypadek krawędzi, który widzę, gdzie to nie zadziała poprawnie, to jeśli w nazwie pliku jest nowy wiersz. Również zachowanie kolorów byłoby miłym dodatkiem, jeśli jest obsługiwane. W przypadku GNU można dodać --color=alwaysdo lsOSX -G.
Graeme
Cześć, polecenie, które wydałeś jest świetne i na pewno mi pomaga, ale zastanawiałem się, czy można użyć powyższego polecenia i jednocześnie zmienić uprawnienia do plików? Próbowałem dodać sudo chmod 777na końcu i dostałem błędy ... Każda pomoc jest bardzo mile
widziana
3
Jeśli chcesz również wykluczyć dowiązania symboliczne, które wskazują na katalogi, zrób to ls -pL | grep -v /. Dodano -Ldereferencje dowiązań symbolicznych.
Matthias Braun
1
Jeśli chcesz również użyć filtru wieloznacznego, zrób to ls -pdL something* | grep -v /. Dodana -dopcja wyświetla same katalogi, a nie ich zawartość, więc zostaną one poprawnie wykluczone.
Rockallite
A jeśli chcesz pobrać wszystkie pliki bez folderów, po prostu usuń -v
jasonleonhard
23

Aby wyświetlić tylko zwykłe pliki:

ls -al | grep '^-'

Z dołączonymi symbolicznymi linkami (do dowolnego typu pliku):

ls -al | grep '^[-l]'

Gdzie pierwszy znak listy opisuje typ pliku, -oznacza to, że jest to zwykły plik, ponieważ link symboliczny to l.

Debian / Ubuntu

Wydrukuj nazwy wszystkich pasujących plików (łącznie z linkami):

run-parts --list --regex . .

Z absolutnymi ścieżkami:

run-parts --list --regex . "$PWD"

Wydrukuj nazwy wszystkich plików, /etcktóre zaczynają się pi kończą na d:

run-parts --list --regex '^p.*d$' /etc
kenorb
źródło
15

lsnie ma takiej możliwości, ale jedną z fajnych rzeczy w unixie i linuksie jest to, że długie i nieeleganckie potoki można łatwo przekształcić w skrypt powłoki, funkcję lub alias. a te z kolei mogą być używane w rurociągach, jak każdy inny program.

(UWAGA: istnieją pewne problemy z zakresem funkcji i aliasów. Skrypty są dostępne dla każdego pliku wykonywalnego, który może je odczytać i wykonać. Aliasy i funkcje są dostępne tylko w bieżącej powłoce - chociaż plik .profile / .bashrc itp. Pod-powłoki może zmienić definicję i tym samym udostępnić je. Ponadto skrypt może być napisany w dowolnym języku - w tym bash / sh, awk, perl, python i inne - w zależności od tego, który z nich jest najlepszy do pracy lub z którego jesteś najbardziej zaznajomiony)

na przykład

alias lsf='find . -maxdepth 1 -type f -print0 | xargs -0r ls'

Dodałem xargs, abyś mógł korzystać ze wszystkich zwykłych lsopcji, nplsf -lrS

Ponieważ używa find, wszystkie normalnie ukryte pliki kropkowe zostaną wyświetlone, a wszystkie nazwy plików będą poprzedzone ./ - to jedyna różnica, którą zauważysz.

Możesz wykluczyć pliki kropkowe, ! -iname '.*'ale wtedy będziesz musiał mieć dwie wersje aliasu - jedną, która wyświetlała pliki kropkowe, a drugą nie.

alias lsf2='find . -maxdepth 1 -type f -a ! -iname '\''.*'\'' -print0 | xargs -0r ls'

Alternatywnie, jeśli lsfbyłby to skrypt zamiast aliasu, można przeanalizować opcje (być może z getopts lub / usr / bin / getopt lub podobnym) i wykluczyć pliki dot, chyba że -abyły obecne.

cas
źródło
-namewystarczy, nie potrzebujesz -iname.
Totor
8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

Opcja -F do ls dołącza * do plików wykonywalnych, / do katalogów, @ do dowiązań symbolicznych, = do gniazd i | do FIFO. Następnie możesz użyć grep, aby wykluczyć nietypowe znaki pliku z pliku wyjściowego i masz pliki. Działa to w dowolnej powłoce, nie tylko w Zsh.

Słabe strony to:

  1. Każdy plik, którego nazwa kończy się @, =lub |zostaną wyłączone (ale nie należy naprawdę mieć pliki z tych znaków w nazwie i tak)
  2. Nie wyklucza to plików urządzeń ani niektórych egzotycznych typów plików w niektórych systemach, takich jak drzwi.
  3. Będziesz miał gwiazdkę dołączoną do każdego pliku, który jest wykonywalny. Można temu zaradzić, przesyłając potokiem przez sed, aby usunąć z wyjścia wszelkie znaki „*”.
  4. To nie działa poprawnie, jeśli istnieją nazwy plików zawierające znaki nowego wiersza.
kurtm
źródło
W systemie mam to na piśmie, 10% pliki mają nazwy zawierające =, @lub |znaki. =jest powszechny w maildir lub nazwach plików, które mają część kodowaną base64 lub cytowaną do wydrukowania. @w definicjach ustawień regionalnych, dla adresów e-mail i nie tylko. Jednak rzadko pojawiają się na końcu nazwy pliku. (na przykład tylko 31 z 2,2 miliona w tym systemie)
Stéphane Chazelas,
3

W instrukcji podano, że opcja „f” dotyczy tylko „zwykłego pliku”, a nie rur, gniazd ani urządzeń blokowych / char, co oznacza, że ​​już robisz właściwe rzeczy.

   -type c
          File is of type c:

          b      block (buffered) special

          c      character (unbuffered) special

          d      directory

          p      named pipe (FIFO)

          f      regular file

          l      symbolic link; this is never true if the -L option or the
                 -follow option is in effect, unless the symbolic link  is
                 broken.  If you want to search for symbolic links when -L
                 is in effect, use -xtype.

          s      socket

          D      door (Solaris)
stokrotka
źródło
0

Nie jest to szczególnie krótkie, ale możesz zmienić go w skrypt lub alias, jeśli chcesz szybko go wywołać. Używając polecenia ls jako tablicy wejściowej, wywołaj ls -ld na każdym wpisie potokowanym do grep, aby wykluczyć katalogi z danymi wyjściowymi wysłanymi do null, a jeśli powiodą się echo oryginalnego wejścia:

for list in `ls` ; do ls -ld $list | grep -v ^d > /dev/null && echo $list ; done ;

Możesz odwrócić grep i wyjście warunkowe, te same wyniki:

for list in `ls` ; do ls -ld $list | grep ^d > /dev/null || echo $list ; done ;
Don R.
źródło
\dev\null?!?!
manatwork
0

To nieco stary wątek, ale najczystszy sposób na wyświetlanie tylko plików.

ls -al | grep '^-' | awk '{print $9}'
RJ
źródło
1
touch "some file name"zobaczyć szybki kontrprzykład
Jeff Schaller
@JeffSchaller Masz ważny punkt. Do tego coś takiego. ls -al | grep '^-' | awk '{ for(i=9; i<=NF; ++i) printf $i""FS; print "" }', powinien obsługiwać pliki ze spacjami.
RJ