Elenca solo i file regolari (ma non le directory) nella directory corrente


126

Posso usare ls -ld */per elencare tutte le voci della directory nella directory corrente. Esiste un modo altrettanto semplice per elencare tutti i file normali nella directory corrente? So di poter usare find

find . -maxdepth 1 -type f

o stat

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

ma questi non mi sembrano eccessivamente eleganti. Esiste un modo semplice per elencare solo i file normali (non mi interessano i dispositivi, le pipe, ecc.) Ma non le sottodirectory della directory corrente? Anche elencare i collegamenti simbolici sarebbe un vantaggio, ma non è una necessità.


5
Cosa intendi con "eccessivamente elegante"? Per quanto ne so, il findcomando è il modo migliore per fare quello che vuoi. Per alcune altre opzioni affidabili, dovresti esaminare i comandi specifici della shell (e quelli sono tutt'altro che portatili)!
Rahmu,

@rahmu Ero per qualcosa di simile a ls -d */, che è breve, facile da scrivere e facile da capire. Quindi sono abbastanza contento della risposta di Ulrich Dangel, anche se non sto usando zsh.
daniel kullmann,

Risposte:


32

Con zshe Glob qualificatori si può facilmente esprimere direttamente, ad esempio:

echo *(.)

restituirà solo l'elenco dei file regolari o un errore a seconda della configurazione.

Per le non directory:

echo *(^/)

(includerà collegamenti simbolici (incluso alle directory), denominati pipe, dispositivi, prese, porte ...)

echo *(-.)

per file regolari e collegamenti simbolici a file regolari.

echo *(-^/)

per non-directory e nemmeno collegamenti simbolici alle directory.

Inoltre, vedi il Dqualificatore globbing se vuoi includere file D ot (file nascosti), come *(D-.).


170
ls -p | grep -v / 

Questo comando elenca tutti i file non nascosti che non sono directory (file normali, collegamenti, file del dispositivo , ecc.). Per includere anche file nascosti, aggiungi l' -Aopzione als

Presuppone che nessuno dei file abbia caratteri di nuova riga nel loro nome. L'aggiunta di -qun'opzione per lstrasformare tutti i caratteri non stampabili tra cui newline ?, garantendo che siano su una riga e quindi adatti per l'alimentazione di un'utilità basata su linee come grepe per la stampa su un terminale.


14
+1, questa è una buona risposta. Il voto negativo di un nuovo utente senza commenti è piuttosto scioccante per me, soprattutto quando viene fornita una risposta funzionante. L'unico caso limite che posso vedere dove questo non funzionerà correttamente è se c'è una nuova riga in un nome file. Anche il mantenimento dei colori sarebbe una buona aggiunta se supportato. Per GNU è possibile aggiungere --color=alwaysa ls, per OSX -G.
Graeme,

Salve, il comando che hai dato è ottimo e sicuramente mi aiuta, tuttavia mi chiedevo se è possibile utilizzare il comando sopra e modificare il permesso del file allo stesso tempo? Ho provato ad aggiungere sudo chmod 777alla fine, e mi hanno dato errori ... Qualsiasi aiuto è molto apprezzato
dissidia

3
Se ti piace anche escludere i collegamenti simbolici che puntano alle directory, fallo ls -pL | grep -v /. I -Lcollegamenti simbolici aggiunti dereferenze.
Matthias Braun

1
Se anche a te piace usare il filtro jolly, fallo ls -pdL something* | grep -v /. L' -dopzione aggiunta elenca le directory stesse, non i loro contenuti, quindi verranno escluse correttamente.
Rockallite,

E se vuoi catturare tutti i file senza cartelle, rimuovi -v
jasonleonhard

23

Per elencare solo i file regolari:

ls -al | grep '^-'

Con collegamenti simbolici (a qualsiasi tipo di file) inclusi:

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

Dove il primo carattere dell'elenco descrive il tipo di file, -significa che si tratta di un file normale, per il collegamento simbolico l.

Debian / Ubuntu

Stampa i nomi di tutti i file corrispondenti (compresi i collegamenti):

run-parts --list --regex . .

Con percorsi assoluti:

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

Stampa i nomi di tutti i file /etcche iniziano con pe finiscono con d:

run-parts --list --regex '^p.*d$' /etc

15

lsnon ha alcuna opzione per farlo, ma una delle cose belle di unix & linux è che le pipeline lunghe e ineleganti possono essere facilmente trasformate in uno script di shell, funzione o alias. e questi, a loro volta, possono essere utilizzati nelle condutture come qualsiasi altro programma.

(NOTA: ci sono alcuni problemi di ambito con funzioni e alias. Gli script sono disponibili per qualsiasi eseguibile in grado di leggerli ed eseguirli. Gli alias e le funzioni sono disponibili solo nella shell corrente, sebbene il .profile / .bashrc di una sotto-shell possa ridefinire e quindi renderli disponibili. Inoltre, uno script può essere scritto in qualsiasi lingua - inclusi bash / sh, awk, perl, python e altri - qualunque sia la migliore per il lavoro o con cui hai più familiarità)

per esempio

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

Ho aggiunto xargs in modo da poter utilizzare tutte le solite lsopzioni, ad eslsf -lrS

Poiché utilizza find, verranno visualizzati tutti i dotfile normalmente nascosti e tutti i nomi di file saranno preceduti da ./ - questa è l'unica differenza che noterai.

Potresti escludere i file dot con, ! -iname '.*'ma poi dovresti avere due versioni dell'alias: una che mostrava i file dot e una no.

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

In alternativa, se lsffosse uno script piuttosto che un alias potresti analizzare le opzioni (forse con getopts o / usr / bin / getopt o simili) ed escludere dotfile a meno che non -afosse presente.


-nameè abbastanza, non è necessario -iname.
Totor

8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

L'opzione -F a ls aggiunge * agli eseguibili, / alle directory, @ ai collegamenti simbolici, = ai socket e | alle FIFO. È quindi possibile utilizzare grep per escludere i caratteri di file non regolari dall'output e si hanno i file. Funzionerà con qualsiasi shell, non solo con zsh.

I punti deboli sono:

  1. Qualsiasi file il cui nome termina in @, =o |saranno esclusi (ma non si dovrebbe davvero avere file con quei caratteri nel nome comunque)
  2. Ciò non esclude i file del dispositivo o alcuni tipi di file esotici su alcuni sistemi come le porte.
  3. Avrai un asterisco aggiunto su qualsiasi file eseguibile. Ciò potrebbe essere gestito eseguendo il piping attraverso sed per rimuovere tutti i caratteri '*' dall'output.
  4. Non funziona correttamente se ci sono nomi di file contenenti caratteri di nuova riga.

Sul sistema che sto scrivendo questo su, il 10% dei file hanno nomi che contengono =, @o |caratteri. =è comune in maildir o nomi di file che hanno una parte codificata base64 o stampabile tra virgolette. @nelle definizioni delle impostazioni internazionali, per indirizzi e-mail e altro. Tuttavia, è raro che appaiano alla fine del nome del file. (solo 31 su 2,2 milioni su questo sistema per esempio)
Stéphane Chazelas,

3

Il manuale affermava che l'opzione 'f' è solo contro 'file normale', non pipe, socket o dispositivi block / char, il che significa che stai già facendo le cose giuste.

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

0

Questo non è particolarmente breve ma potresti trasformarlo in uno script o in un alias se dovessi chiamarlo rapidamente. Usando il comando ls come array di input, chiama ls -ld su ogni voce convogliata a grep per escludere le directory con l'output inviato a null e, in caso di successo, fare eco all'input originale:

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

È possibile invertire grep e output condizionato, stessi risultati:

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

\dev\null?!?!
arte


0

Questo è un thread un po 'vecchio, ma il modo più pulito per elencare solo i file.

ls -al | grep '^-' | awk '{print $9}'


1
touch "some file name"per vedere un rapido controesempio
Jeff Schaller

@JeffSchaller Hai un punto valido. Per questo qualcosa del genere. ls -al | grep '^-' | awk '{ for(i=9; i<=NF; ++i) printf $i""FS; print "" }', dovrebbe gestire i file con spazi al loro interno.
RJ,
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.