Come ordinare prima le directory, quindi i file, ecc ... quando si usa "ls" in Unix


91

Vorrei usare il lscomando per mostrare prima le directory e poi i file. Provai:

ls -la | sort -k 1

Ma ho ricevuto un ordine sbagliato.


è perché -viene prima dquando si utilizzasort
Nifle

4
Le testine unix dei vecchi tempi (quelle dell'era pre-GUI) utilizzate per scrivere in maiuscolo i nomi delle loro cartelle e rendere i nomi di file semplici non capitalizzati per ottenere quel risultato automagicamente.
JRobert,

Domanda utile! Forse è il momento di cambiare la risposta accettata in una più semplice e che non rompe i colori dei terminali?
Ippi,

Provals -lh --group-directories-first
Diogo,

Risposte:


28

Il seguente comando elencherà prima le directory, i file ordinari secondo e i collegamenti terzi.

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

Inoltre, sarebbe molto sensato creare un alias per questo comando per salvare i tasti.

Modificare:

Se prima vuoi le directory e poi tutto ciò che non è una directory, usa questo:

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


1
Questo comando non elenca tutto se ci sono, ad esempio, socket o FIFO nella cartella
Studer,

1
Quella versione modificata dovrebbe funzionare ancora con altri tipi. Il primo grep dice tutto ciò che inizia con una 'd', e il secondo dice tutto ciò che non inizia con una 'd'. Sicuramente tutto inizia con l'annuncio o no, giusto?
Ry4an Brase,

1
@ Marco - Perché non fare: ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total"?
FCTW

1
Per rendere il comando di @ FCTW un alias OSX, aggiungilo al tuo ~ / .profile:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind

2
Ho trovato una notazione più breve funzionante: ls -la|grep ^d;ls -la|grep -v ^d(le virgolette non sono obbligatorie e sostituite &&con ;). Un'altra opzione è quella di introdurre una variabile e poi valutare: a="ls -la|grep ^d";eval $a;eval $a -v. Potrebbe essere utile per evitare le ripetizioni quando sono specificate molte più opzioni su ls/ grep. C'è anche questa ls -la --group-directories-firstopzione, comunque l'imo più corto èls -la|sort
Steven Pribilinskiy,

205

Adoro * nix e amo vedere l'inventiva che si cela in alcune di queste risposte ...

Il mio non è così elegante su GNU Linux:

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

Dato che mi sento più a mio agio con le mie app CLI per Linux, tendo ad aggiornare anche coreutils su OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'

6
sfortunatamente, questo non funziona sul terminale osx, poiché l'opzione - non è disponibile.
MEM,

7
re amore: è quel sarcasmo? Se è così, sono d'accordo.
codice alleato

4
Scopo di alias ls è definire gli elementi di configurazione che voglio usare il 90% delle volte. Meno tasti per ottenere l'output desiderato. Se mai vuoi avere l'output nativo di ls puoi sempre / bin / ls.
jonathanserafini,

4
@MEM Se stai usando OS X e ti piace usare Terminal, brew install bash allora dovresti , allora funzionerà! :)
Andrew Ashbacher,

5
La mia opinione: questa avrebbe dovuto essere la risposta accettata in quanto elenca un'opzione della riga di comando per raggiungere esattamente l'obiettivo, anziché un insieme contorto di grep ecc.
Ryan Griggs,

17

Coreutils per utenti Mac :

brew install coreutils

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

Supponendo che il tuo sistema sia pronto per l' homebrew :


7
glspiuttosto. Giusto?
Paul Irish,

1
Sì, per impostazione predefinita. Puoi anche usare coreutils di default con PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
benesch,

7

Ci sono alcune cose che voglio vedere in un elenco di directory, e finora nessuna delle risposte qui soddisfa tutti i requisiti di seguito. I miei requisiti per un elenco di directory:

  1. Directory e file sono ordinati alfabeticamente
  2. Le directory sono elencate per prime
  3. I collegamenti simbolici (collegamenti simbolici) sono ordinati come file
  4. L'ordinamento non fa distinzione tra maiuscole e minuscole
  5. L'ordinamento ignora tutti i principali caratteri non alfa in un nome file
  6. L'elenco include il conteggio totale di directory (esclusi ./e ../), file e collegamenti
  7. L'elenco include la dimensione totale (utilizzo del disco) di directory e file
  8. L'elenco deve avere lo stesso aspetto su Linux e Windows (Git Bash shell): questo è stato il più difficile da ottenere in quanto opzioni convenienti come --group-directories-firstnon funzionano in Git Bash per Windows

Dopo molti hacking, ho finalmente trovato un one-liner (anche se una linea molto lunga ;-)) di cui sono soddisfatto. Ho assegnato questo a un alias chiamato '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\)

Per rendere le cose più facili da gestire, mi sono venuti in mente comandi separati per l'output di ogni segmento dell'elenco delle directory di mio gradimento, quindi li ho assemblati insieme usando l' &&operatore.

  • ls -dlF --color * .* | head -n2- Estrai ./e ../. Non vogliamo passare attraverso questi sortperché sono già nell'ordine corretto e l'ordinamento può comportare la ../prima elencazione. L' -dopzione è di sbarazzarsi della linea "totale"; Mi piace aggiungere -Fper mostrare la barra finale per le directory (segnerà anche i collegamenti simbolici con "@" quando si fa una pianura ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Estrai le directory e ordinale per nome file (nona colonna), ignorando sia i caratteri non alfa / spaziali ( dopzione) sia i caratteri maiuscoli ( fopzione). L' ls -Aopzione esclude ./e ../dall'elenco poiché li abbiamo già estratti nel passaggio precedente. Tendo a precedere tutto grepe i sortcomandi con il LC_ALL=Cripristino delle impostazioni internazionali in modo che (1) l'output sia coerente tra le shell Unix e (2) a volte puoi vedere prestazioni più veloci poiché non ha più l'overhead del pesante carattere UTF-8 impostato su avere a che fare con.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Questo è simile al passaggio precedente, ma questa volta stiamo ordinando file e collegamenti simbolici.

  • find -maxdepth 1 -type d ! -name . | wc -l- Ottieni il numero di directory, esclusi ./e ../.

  • find -maxdepth 1 -type f | wc -l - Ottieni il numero di file.

  • find -maxdepth 1 -type l | wc -l - Ottieni il numero di symlink.

  • du -hs | cut -f 1 - Estrai la dimensione totale di tutte le sottodirectory in formato leggibile dall'uomo.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Estrai la dimensione totale di tutti i file in formato leggibile dall'uomo.

Vediamo il nostro nuovo diralias in azione!

PRIMA:

$ 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/

DOPO:

$ 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)

Uno svantaggio minore è che non puoi avere elenchi colorati, poiché i caratteri di controllo del colore che circondano i nomi dei file rendono l'ordinamento troppo inaffidabile.


AGGIORNARE

L'alias sopra era dolorosamente lento quando eseguito dalla directory principale di un file system profondo, quindi ho aggiornato a questo comando più semplice ma molto più performante:

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

Uscita campione:

$ 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

Poiché la nuova versione di Git Bash per Windows supporta --group-directories-first, non è più necessario ripiegare sort. Anche se il nuovo alias non mostra quante più informazioni del precedente alias, i guadagni in termini di prestazioni sono più che ne vale la pena. Come vantaggio, ottieni anche i colori!


Bella risposta! Ma quando dici: "Dopo aver hackerato molto, alla fine mi è venuta in mente una one-liner ..." Sì, davvero non è proprio una "one-liner" in senso classico. Potrebbe avere senso prendere quella logica e renderla uno script shell autonomo ed eseguirlo o chiamarlo come alias.
Jake Gould,

@JakeGould Sei veloce! Non ho ancora finito di rileggere la mia risposta e hai già finito di leggerlo e hai rilasciato un commento :). Sì, è un candidato principale per una funzione, ma ero troppo pigro al momento, quindi l'ho semplicemente buttato nel mio file .bash_aliases. D'altra parte, di solito scrivo una funzione solo quando non riesco a fare qualcosa senza passare parametri.
thdoan

@ 10basetom: domanda veloce: come si ottengono i diversi colori per le colonne in ls? Posso colorare i nomi dei file per tipo di file usando ls --color, ma non vedo un modo per ottenere quei colori utili per le colonne. Qual è il segreto?
Pirx,

@Pirx Credo che le colonne siano colorate dall'evidenziazione della sintassi di Stack Exchange predefinita :-).
entro il

Sì, sembra che sia così, ma è un'ottima idea, e le soluzioni sono in ;-)
Pirx

6

Hai diverse scelte, a seconda se vuoi mantenere l'ordine alfabetico.

Potresti semplicemente provare:

ls -al | ordina -k1 -r

o questo, per mantenere l'ordine alfabetico per i file con le stesse autorizzazioni:

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

o, come diceva undici81 (ma questa versione elenca tutto):

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


1
Questa è una soluzione migliore IMO. L'uso di più processi e pipe per eseguire l'ordinamento anziché le tubazioni per ordinare sembra un po 'arretrato. Soprattutto dal momento che ls- al|sort -k1 -rfunziona. Ciò che mancava è solo la -rbandiera.
brice

@brice La cosa che mi preoccupa di 'tipo' è che ./e ../non saranno le prime due righe, in questo ordine. A parte questo, sono d'accordo che sia la soluzione più efficiente.
thdoan

Come colorare l'output?
Danijel,

5

Alla risposta delerious010 , aggiungerei che se si desidera un ordinamento vecchio stile:

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

(oppure usa LC_ALL o LANGUAGE o LC_COLLATE impostato su "C").

Questo darà qualcosa di simile a:

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

Anche se, se ricordo bene, i file di punti nascosti apparivano originariamente prima delle directory.


2

Ecco una funzione per fare questo (bash o zsh): E ... Non sto suggerendo che questo è il modo migliore, ma è quello che ho inventato e sto usando in questo momento:

funzione lss
{
    # Mostra l'elenco delle directory con le directory in alto.

    comando ls --color = sempre $ @ | egrep '^ d | totale'
    comando ls --color = sempre $ @ | egrep -v '^ d | total';
}

Solo un problema, questo non sembra funzionare. È necessario utilizzare il formato di elenco lungo ( ls -l) per filtrare in base al tipo di file in questo modo. Inoltre, questo comando si interromperà sugli spazi (in bash). Devi citare in questo modo: "$@"Se vuoi usare questo approccio, potresti fare qualcosa del genere:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Sei

2

ls -laX ti mostrerà prima le directory in ordine alfabetico, ma rovinerà l'elenco dei file.

Opzioni lunghe:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension

Funzionerebbe solo se si potesse essere assolutamente certi che ogni directory non avesse punti nel suo nome.
undici81,

1

Un altro modo ...

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

O

ls -la | sort -r

O

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"

Cosa fanno questi? Dove hai imparato a digitarli?
Tamara Wijsman,

Bene, il mio sistema operativo preferito è Debian Linux. La versione del pacchetto gnu core utils di Debian di ls supporta l'opzione --show-directories-first ... quando ho iniziato a usare OSX ho semplicemente preso tutti i miei file bash dot dalla mia casella Debian e li ho lasciati nella mia directory home ... I aveva un sacco di bash_aliases che si sono rotti così ... Fu allora che dovetti escogitare qualche soluzione per i miei alias ...
Eddie B

Il primo è un po 'ridondante ... Non c'è davvero alcun motivo di ordinare per le directory in quanto è l'ordine che dobbiamo modificare non le directory ... il' ls -la | sort -r 'è ciò che funziona davvero. Fondamentalmente sta affermando ... 1) A) Trova. -d 1 -type d (Inizia da questa directory, cerca una profondità di directory e cerca solo le directory) B) ls -la (elenca tutti gli attributi dei file) C) Ordina in ordine inverso 2) Fai come 1) rilascia la ricerca. .. non è necessario ... In realtà mi piace di più la soluzione di 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

Spiegazione

Uso una combinazione delle soluzioni fornite nelle risposte e nei commenti qui.

Predefinito ls

Innanzitutto, sovrascrivo il comportamento predefinito per ls:

  • -l: Visualizza sempre l'elenco come un elenco monodimensionale e verticale
  • -h: Visualizza le dimensioni dei file in modo leggibile dall'uomo (ad es. 4.0K anziché 4096)
  • -F: Visualizza gli indicatori come una barra finale per le directory
alias ls='ls -lhF --color'

estesa ll

Successivamente, scrivo una funzione contenente la logica di ordinamento. Per ognuno lspasso qualsiasi argomento originariamente passato ad esso. Ciò mi consente di utilizzare l'alias da una directory di lavoro diversa da quella che desidero elencare (ad es ls -a ~.).

Inoltre, ogni chiamata a lsviene reindirizzata a un grepcomando. Qui, l'ordinamento avviene. ls -l | grep "^d"ad esempio elenca solo le directory. Se le directory devono essere elencate per prime, anche questa deve venire prima nella funzione. La prossima cosa sono i file.

Infine, mostro tutto ciò che non è né una directory né un file (né la riga che mostra la dimensione totale del contenuto della directory). Questo viene fatto avviando directoy, voci di file regolari e la voce totale e quindi invertendo il risultato tramite l' -vargomento.

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"
}

Infine, alias la funzione su un nuovo comando. In particolare, non voglio sovrascrivere lsnel caso in cui la mia funzione si interrompa in alcuni scenari. Quindi voglio essere in grado di usare ls. In alternativa, puoi sempre invocare il lscomando senza alias invocando \ls.

alias ll=list_sorted

Appunti

  • Uso ;invece &&come delimitatore per i comandi. Altrimenti, non è possibile elencare i contenuti delle directory che non contengono directory (il primo comando ls viene valutato come falso, quindi non consente l'esecuzione del comando successivo poiché è accoppiato con &&. ;Evita quello.)

0

Questa è una soluzione di script. Elenca solo i nomi, nessun dato inode, alfabetico, senza distinzione tra maiuscole e minuscole, formattato in colonne. Sebbene sia il maggiore di riga anziché il maggiore di colonna come l'output predefinito di ls. Le colonne diventano un po 'confuse se c'è un nome file con> 26 caratteri.

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[@]}"

E un altro, con qualche formattazione extra.

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[@]}"

L'output per l'ultimo è simile al seguente, meno i colori:

  ---- 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

Basta ricordare di non alias o modificare il comportamento predefinito di ls poiché questo script lo chiama.

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.