Jak posortować pierwsze katalogi, a potem pliki itp.… Podczas używania „ls” w Uniksie

91

Chciałbym użyć lspolecenia, aby najpierw wyświetlić katalogi, a następnie pliki. Próbowałem:

ls -la | sort -k 1

Ale mam złe zamówienie.

atricapilla
źródło
to dlatego, że -pojawia się przed dużyciemsort
Nifle
4
Dawne głowy uniksowe (te z epoki wcześniejszego GUI) używały wielkich liter w nazwach folderów i czyniły proste nazwy plików niekapitalizowanymi, aby automatycznie uzyskać ten wynik.
JRobert
Przydatne pytanie! Być może nadszedł czas, aby zmienić przyjętą odpowiedź na prostszą i nie psującą kolorów terminali?
ippi
Spróbujls -lh --group-directories-first
Diogo,

Odpowiedzi:

28

Następujące polecenie wyświetli katalogi jako pierwsze, zwykłe pliki jako drugie, a łącza trzecie.

ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"

Ponadto sensowne byłoby utworzenie aliasu dla tego polecenia, aby zapisać naciśnięcia klawiszy.

Edytować:

Jeśli chcesz najpierw katalogów, a następnie wszystkiego, co nie jest drugim katalogiem, użyj tego:

ls -la | grep "^d" && ls -la | grep -v "^d"

jedenaście81
źródło
1
To polecenie nie wyświetla wszystkiego, jeśli w folderze znajdują się na przykład gniazda lub FIFO
Studer
1
Ta edytowana wersja powinna nadal działać z innymi typami. Pierwszy grep mówi wszystko, co zaczyna się na „d”, a drugi mówi wszystko, co nie zaczyna się na „d”. Na pewno wszystko zaczyna się od reklamy, czy nie, prawda?
Ry4an Brase
1
@Mark - Dlaczego po prostu nie robić: ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total"?
FCTW
1
Aby polecenie @ FCTW było aliasem OSX, dodaj to do ~ / .profile:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind
2
Znalazłem krótszą notację roboczą: ls -la|grep ^d;ls -la|grep -v ^d(cytaty nie są wymagane i zastępowane &&przez ;). Inną opcją jest wprowadzenie zmiennej, a następnie oceniają go: a="ls -la|grep ^d";eval $a;eval $a -v. Może być użyteczny, aby uniknąć powtórzeń, gdy dla ls/ podano więcej opcji grep. Jest też taka ls -la --group-directories-firstopcja, jednak najkrótsze imo tols -la|sort
Steven Pribilinskiy
204

Uwielbiam * nix i uwielbiam pomysłowość, która dotyczy niektórych z tych odpowiedzi ...

Mój nie jest tak fantazyjny w GNU Linux:

alias ls='ls --color -h --group-directories-first'

Biorąc pod uwagę, że czuję się bardziej komfortowo z aplikacjami CLI dla Linuksa, zwykle aktualizuję coreutils w OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
jonathanserafini
źródło
6
nie działa to niestety na terminalu osx, ponieważ opcja nie jest dostępna.
MEM
7
re love: Czy to jest sarkazm? Jeśli tak, zgodziłbym się.
allyourcode
4
Celem aliasu ls jest zdefiniowanie elementów konfiguracji, których chcę używać przez 90% czasu. Mniej naciśnięć klawiszy, aby osiągnąć pożądaną moc wyjściową. Jeśli kiedykolwiek chcesz mieć natywne wyjście ls, zawsze możesz / bin / ls.
jonathanserafini,
4
@MEM Jeśli używasz OS X i lubisz korzystać z terminala, powinieneś brew install bash wtedy, to zadziała! :)
Andrew Ashbacher
5
Moja opinia: to powinna być zaakceptowana odpowiedź, ponieważ zawiera opcję wiersza poleceń umożliwiającą osiągnięcie dokładnie celu, zamiast złożonego zestawu grepów itp.
Ryan Griggs
17

Dla użytkowników komputerów Mac coreutils :

brew install coreutils

alias ls='ls --color -h --group-directories-first'

Zakładając, że twój system jest gotowy do homebrew :

Wadym Tyemirow
źródło
7
glsraczej. Dobrze?
Paul Irish,
1
Tak, domyślnie. Możesz także domyślnie używać coreutils PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
benesch
7

Są pewne rzeczy, które chcę zobaczyć na liście katalogów, a jak dotąd żadna z odpowiedzi tutaj nie spełnia wszystkich poniższych wymagań. Moje wymagania dotyczące katalogu:

  1. Katalogi i pliki są sortowane alfabetycznie
  2. Katalogi są wymienione jako pierwsze
  3. Dowiązania symboliczne (dowiązania symboliczne) są sortowane jak pliki
  4. Sortowanie nie uwzględnia wielkości liter
  5. Sortowanie ignoruje wszystkie wiodące znaki inne niż alfa w nazwie pliku
  6. Lista zawiera całkowitą liczbę katalogów (z wyłączeniem ./i ../), plików i łączy
  7. Lista zawiera całkowity rozmiar (użycie dysku) katalogów i plików
  8. Lista musi wyglądać tak samo w systemie Linux i Windows (powłoka Git Bash) - było to najtrudniejsze do uzyskania, ponieważ wygodne opcje, takie jak --group-directories-firstnie działają w Git Bash dla Windows

Po wielu włamaniach, w końcu wymyśliłem linijkę (choć bardzo długą linię ;-)), z której jestem zadowolony. Przypisałem to aliasowi o nazwie „dir”:

ls -dlF --color * .* | head -n2 && ls -AlF | LC_ALL=C grep "^d" | 
LC_ALL=C sort -k 9df && ls -AlF | LC_ALL=C grep "^[l-]" | 
LC_ALL=C sort -k 9df && echo -e `find -maxdepth 1 -type d ! -name . | 
wc -l` Dir\(s\) `du -hs | cut -f 1`\\t\\t`find -maxdepth 1 -type f | 
wc -l` File\(s\) `find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | 
tail -n 1 | cut -f 1`\\t\\t`find -maxdepth 1 -type l | wc -l` Link\(s\)

Aby ułatwić zarządzanie, wymyśliłem osobne polecenia, które wypisują każdy segment listy katalogów według moich upodobań, a następnie złożyłem je razem za pomocą &&operatora.

  • ls -dlF --color * .* | head -n2- Ekstrakt ./i ../. Nie chcemy ich przekazywać, sortponieważ są one już we właściwej kolejności, a ich sortowanie może spowodować, ../że zostaną wymienione jako pierwsze. -dOpcją jest, aby pozbyć się linii „całkowitą”; Lubię dodawać, -Faby wyświetlać ukośnik końcowy dla katalogów (będzie również oznaczać dowiązania symboliczne „@”, gdy robisz zwykły ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Wyodrębnij katalogi i posortuj je według nazwy pliku (9 kolumna), ignorując zarówno znaki inne niż alfabetyczne / spacje ( dopcja), jak i wielkość liter ( fopcja). W ls -Awyklucza opcji ./i ../od notowań skoro już ekstrakcji je w poprzednim kroku. Mam tendencję do prefiksu wszystkich grepi sortpoleceń z LC_ALL=Cresetowaniem ustawień regionalnych, aby (1) dane wyjściowe były spójne w powłokach uniksowych i (2) czasami można zobaczyć większą wydajność, ponieważ nie ma już narzutu ciężkiego zestawu znaków UTF-8 na radzić sobie z.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Jest to podobne do powyższego kroku, ale tym razem sortujemy pliki i dowiązania symboliczne.

  • find -maxdepth 1 -type d ! -name . | wc -l- Uzyskaj liczbę katalogów, z wyłączeniem ./i ../.

  • find -maxdepth 1 -type f | wc -l - Uzyskaj liczbę plików.

  • find -maxdepth 1 -type l | wc -l - Uzyskaj liczbę dowiązań symbolicznych.

  • du -hs | cut -f 1 - Wyodrębnij całkowity rozmiar wszystkich podkatalogów w formacie czytelnym dla człowieka.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Wyodrębnij całkowity rozmiar wszystkich plików w formacie czytelnym dla człowieka.

Zobaczmy nasz nowy diralias w akcji!

PRZED:

$ ls -alF
total 22
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/

PO:

$ dir
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
      5 Dir(s) 2.8M           6 File(s) 31K           0 Link(s)

Jednym drobnym minusem jest to, że nie można mieć kolorowych list, ponieważ znaki sterujące kolorem otaczające nazwy plików powodują, że sortowanie jest zbyt niewiarygodne.


AKTUALIZACJA

Powyższy alias był boleśnie powolny po uruchomieniu z katalogu głównego głębokiego systemu plików, więc zaktualizowałem to prostsze, ale o wiele bardziej wydajne polecenie:

ls -AFoqv --color --group-directories-first | tail -n +2 && find -maxdepth 1 -type f -printf '%s\n' | awk '{total+=$1} END {print total" bytes"}'

Przykładowe dane wyjściowe:

$ dir
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .aws/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .gem/
drwxr-xr-x 1 Tom     0 Mar 29 19:32 .ssh/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .zbstudio/
drwxr-xr-x 1 Tom     0 Jun 16  2016 temp/
drwxr-xr-x 1 Tom     0 Jul 13  2016 vimfiles/
-rw-r--r-- 2 Tom   365 Mar 30 10:37 .aliases
-rw-r--r-- 1 Tom 16028 Mar 30 12:12 .bash_history
-rw-r--r-- 2 Tom  2807 Mar 30 12:12 .bash_profile
-rw-r--r-- 2 Tom  2177 Mar 29 23:24 .functions
-rw-r--r-- 1 Tom  1091 Mar 30 10:34 .gitconfig
-rw-r--r-- 1 Tom  8907 Mar 29 14:45 _viminfo
-rw-r--r-- 1 Tom  2444 Jul 13  2016 _vimrc
33819 bytes

Ponieważ nowa wersja Git Bash obsługuje system Windows --group-directories-first, nie musimy już na niej polegać sort. Mimo że nowy alias nie wyświetla tyle informacji, co poprzedni alias, wzrost wydajności jest więcej niż wart. Jako profit otrzymasz także kolory!

thdoan
źródło
Świetna odpowiedź! Ale kiedy mówisz: „Po wielu włamaniach, w końcu wymyśliłem jedną linijkę…” Tak, w rzeczywistości nie jest to tak naprawdę „jedna linijka” w klasycznym sensie. Logiczne może być przyjęcie tej logiki i uczynienie z niej samodzielnego skryptu powłoki i uruchomienie go lub wywołanie go jako aliasu.
JakeGould
@JakeGould Jesteś szybki! Jeszcze nie skończyłem korekty mojej odpowiedzi, a ty już ją przeczytałeś i wystrzeliłeś komentarz :). Tak, jest to główny kandydat na funkcję, ale byłem wtedy zbyt leniwy, więc po prostu wrzuciłem ją do mojego pliku .bash_aliases. Z drugiej strony zwykle piszę funkcję tylko wtedy, gdy nie mogę zrobić czegoś bez podania parametrów.
thdoan
@ 10basetom: Szybkie pytanie: Jak uzyskać różne kolory dla kolumn w ls? Mogę pokolorować nazwy plików według rodzaju pliku za pomocą ls --color, ale nie widzę sposobu na uzyskanie tych pomocnych kolorów dla kolumn. Jaki jest sekret
Pirx
@Pirx Uważam, że kolumny są kolorowe według domyślnego podświetlenia składni Stack Exchange :-).
thdoan
Tak, wydaje się, że tak jest, ale to świetny pomysł, a rozwiązania są ;-)
Pirx
6

Masz kilka możliwości, w zależności od tego, czy chcesz zachować porządek alfabetyczny.

Możesz po prostu spróbować:

ls -al | sortuj -k1 -r

lub to, aby zachować porządek alfabetyczny dla plików z tymi samymi uprawnieniami:

ls -al | sortuj -k1,1 -k9,9 -r

lub, jak powiedział jedenaście81 (ale ta wersja zawiera wszystko):

ls -la | grep "^ d" && ls -la | grep "^ -" && ls -al | grep -v "^ [d | -]"

Studer
źródło
1
To jest ładniejsze rozwiązanie IMO. Używanie kilku procesów i potoków do sortowania zamiast potokowania do sortowania wydaje się nieco odwrócone. Zwłaszcza, że ls- al|sort -k1 -rdziała. Brakowało tylko -rflagi.
brice
@brice The rzeczą, która przeszkadza mi o „rodzaju” jest to, że ./i ../nie będzie pierwszym dwie linie, w tej kolejności. Poza tym zgadzam się, że jest to bardziej wydajne rozwiązanie.
thdoan
Jak pokolorować wydruk?
Danijel
5

Do odpowiedzi delerious010 dodam, że jeśli chcesz zamówić w starym stylu:

LANG=C ls -la --group-directories-first

(lub użyj LC_ALL lub LANGUAGE lub LC_COLLATE ustawionych na „C”).

To da coś podobnego do:

.
..
DIR
Dir
dir
.hidden
123
UC_FILE
Uc_file
lc_file

Chociaż, o ile dobrze pamiętam, ukryte pliki kropek pierwotnie pojawiły się przed katalogami.

Dennis Williamson
źródło
2

Oto funkcja pozwalająca to zrobić (bash lub zsh): I ... Nie sugeruję, że to najlepszy sposób, ale to ten, który wymyśliłem i używam teraz:

funkcja lss
{
    # Pokazuje listę katalogów z katalogami u góry.

    polecenie ls --color = zawsze $ @ | egrep „^ d | total”
    polecenie ls --color = zawsze $ @ | egrep -v '^ d | total';
}
SuperMagic
źródło
Po prostu to nie wydaje się działać. Musisz użyć formatu długiej listy ( ls -l), aby filtrować według typu pliku tego typu. Również to polecenie będzie działać na spacjach (w bash). Musisz cytować w ten sposób: "$@"Jeśli chcesz zastosować to podejście, możesz zrobić coś takiego:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Sześć
2

ls -laX pokaże najpierw katalogi w kolejności alfabetycznej, ale przekręci listę plików.

Długie opcje:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension
Konstabl
źródło
Działa to tylko wtedy, gdy masz absolutną pewność, że w każdym katalogu nie ma kropek w nazwie.
jedenaście81
1

Inny sposób ...

find . -d 1 -type d | ls -la | sort -r 

LUB

ls -la | sort -r

LUB

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"
Eddie B.
źródło
Co one robią? Gdzie nauczyłeś się je pisać?
Tamara Wijsman,
Cóż, moim preferowanym systemem operacyjnym jest Debian Linux. Debianowa wersja pakietu gnu core utils pakietu ls obsługuje opcję --show-directories-first ... kiedy zacząłem używać OSX, po prostu wziąłem wszystkie moje pliki kropek bash z mojego pudełka Debiana i upuściłem je w katalogu domowym ... I miałem wiele bash_aliases, które się zepsuły, więc ... Wtedy musiałem wymyślić kilka sposobów obejścia moich aliasów ...
Eddie B,
Pierwszy jest nieco redundantny ... Naprawdę nie ma powodu, aby sortować katalogi, ponieważ jest to kolejność, w której musimy modyfikować nie katalogi ... the 'ls -la | sort -r 'jest tym, co naprawdę działa. Zasadniczo oznacza to ... 1) A) Znajdź. -d 1 -typ d (Zacznij od tego katalogu, przeszukaj jedną głębokość katalogu i wyszukaj tylko katalogi) B) ls -la (wyświetla listę wszystkich atrybutów) C) Sortuj je w odwrotnej kolejności 2) Wykonaj jak 1) po prostu usuń znalezisko. .. nie jest potrzebne ... Właściwie bardziej podoba mi się rozwiązanie Studers ... :-)
Eddie B
1

TL; DR

alias ls='ls -lhF --color'

list_sorted() {
    ls $* | grep "^d";
    ls $* | grep "^-";
    ls $* | grep -v -E "^d|^-|^total"
}

alias ll=list_sorted

Wyjaśnienie

Korzystam z kombinacji rozwiązań zawartych w odpowiedziach i komentarzach tutaj.

Domyślna ls

Przede wszystkim nadpisuję domyślne zachowanie dla ls:

  • -l: Zawsze wyświetlaj listę jako jednowymiarową, pionową listę
  • -h: Wyświetlaj rozmiary plików w sposób czytelny dla człowieka (np. 4,0 KB zamiast 4096)
  • -F: Wyświetlanie wskaźników takich jak ukośnik końcowy dla katalogów
alias ls='ls -lhF --color'

Rozszerzony ll

Następnie piszę funkcję zawierającą logikę sortowania. Do każdego lsprzekazuję wszelkie pierwotnie przekazane mu argumenty. To pozwala mi używać aliasu z innego katalogu roboczego niż ten, który chcę wyświetlić (tj ls -a ~.).

Ponadto każde wywołanie do lsjest przesyłane potokowo do greppolecenia. Tutaj odbywa się sortowanie. ls -l | grep "^d"na przykład wyświetla tylko katalogi. Jeśli katalogi powinny być wymienione jako pierwsze, musi to również zająć pierwsze miejsce w funkcji. Następną rzeczą są pliki.

Na koniec pokazuję wszystko, co nie jest ani katalogiem, ani plikiem (ani wierszem pokazującym całkowity rozmiar zawartości katalogu). Odbywa się to poprzez grepowanie directoy, zwykłych wpisów w plikach i całkowitego wpisu, a następnie odwrócenie wyniku za pomocą -vargumentu.

list_sorted() {
    # List directories
    ls $* | grep "^d";
    # List regular files
    ls $* | grep "^-";
    # List everything else (e.g. symbolic links)
    ls $* | grep -v -E "^d|^-|^total"
}

Wreszcie alias funkcji do nowego polecenia. W szczególności nie chcę nadpisywać lsna wypadek, gdyby moja funkcja uległa awarii w niektórych scenariuszach. Potem chcę móc korzystać ls. Alternatywnie możesz zawsze wywołać niezaaloryzowane lspolecenie, wywołując \ls.

alias ll=list_sorted

Notatki

  • Używam ;zamiast &&jako separatora poleceń. W przeciwnym razie nie będzie można wyświetlić zawartości katalogów niezawierających katalogów (pierwsza komenda ls ma wartość false, co uniemożliwia wykonanie następnej komendy, ponieważ jest ona połączona z &&. ;Unika tego.)
kleinfreund
źródło
0

To jest rozwiązanie skryptowe. Wyświetla tylko nazwy, brak danych i-węzłów, alfabetycznie, bez rozróżniania wielkości liter, sformatowane w kolumny. Chociaż jest to wiersz-major zamiast kolumny major, jak domyślne wyjście ls. Kolumny stają się nieco nieporządne, jeśli nazwa pliku ma> 26 znaków.

rm -f /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout

IFS=$'\n' read -d '' -r -a lines < /tmp/lsout

printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

I jeszcze jedno, z dodatkowym formatowaniem.

rm -f /tmp/lsout
echo "  ---- Directories ---- " >> /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

rm -f /tmp/lsout
echo "  ------- Files ------- " >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Wyjście dla ostatniego wygląda następująco, bez kolorów:

  ---- Directories ----   archive/                  bookmarks/              
Desktop/                  Documents/                Downloads/              
fff/                      health/                   Library/                
Movies/                   Music/                    Pictures/               
Public/                   rrf/                      scifi/            
testdir/                  testdir2/                                         
  ------- Files -------   @todo                     comedy            
delme                     lll                       maxims                  
schedule                  vtokens style

Pamiętaj tylko, aby nie aliasować ani nie zmieniać domyślnego zachowania ls, ponieważ ten skrypt go wywołuje.

Igorio
źródło