Ottieni un elenco di nomi di directory con find


35

So di poterlo fare per ottenere un elenco di nomi di directory:

find . -type d -maxdepth 1 

L'output è simile al seguente:

.
./foo
./bar

Preferisco l'elenco senza ./. C'è un modo per trovare trovare l'output solo dei nomi grezzi?

Ho provato a inviare l'elenco a stat per formattarlo, ma questo mi dà lo stesso risultato:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'

quindi vuoi foo bar ...tutto su una riga senza il ./davanti?
Levon,

Questo è puramente per motivi estetici / estetici o stai cercando di fare qualcosa con l'output?
jw013,

Risposte:


42

Con GNU findpuoi usare l' -printfopzione:

find . -maxdepth 1 -type d -printf '%f\n'

Come notato da Paweł nei commenti, se non si desidera elencare la directory corrente aggiungere -mindepth 1, ad esempio:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'

Non trovo alcuna menzione -printfdell'opzione nelle ultime specifiche POSIX e mi chiedo quanto sia portatile ...
rahmu

@rahmu: questo è stato testato con GNU find. Nessuna delle printfopzioni è menzionata da POSIX e non sembrano essere supportate da alcune delle altre findversioni. GNU find può essere installato nella maggior parte dei luoghi, quindi in questo senso è portatile.
Thor,

1
aggiungi anche -mindepth 1se vuoi sbarazzarti del.
Paweł Prażak,

18

Aggiornare:

Un'alternativa più breve:

 find . -maxdepth 1 -type d | cut -c 3-

Ti darà i nomi, uno per riga, senza barre


4
@downvoter .. un downvote senza spiegazione non aiuta nessuno (OP, SO o me). Questa è una soluzione funzionale alla domanda di OP. Sono felice di correggere un errore se sottolineato o migliorare la risposta, ma ciò richiede un feedback costruttivo piuttosto che un semplice "clic" anonimo.
Levon,

1
Sono quello che ha effettuato il downgrade quando la tua risposta includeva l'analisi ls. Allo stesso tempo, avevo pubblicato un link sul perché questa è una cattiva idea su un'altra risposta che è stata eliminata da allora. All'epoca c'erano solo 2 risposte e il motivo sembrava ovvio. Sono contento che tu abbia sottolineato l'ambiguità, ed ecco la mia spiegazione. Per la cronaca, ho convertito il mio downvote in un voto perché sono d'accordo con la tua risposta attuale.
rahmu,

@rahmu Dare una spiegazione per il tuo voto negativo in un'altra domanda non mi è di aiuto (e solo ovvio per te). Inoltre, sebbene questa sia una soluzione migliore, la soluzione che avevo pubblicato in precedenza ha funzionato bene (sì, ho familiarità con il link "non usare ls", ma non si applica ciecamente in tutti i casi). Se hai un contro esempio del perché la mia soluzione iniziale non avrebbe funzionato, mi piacerebbe conoscerlo (in modo che io possa effettivamente imparare qualcosa da questo), altrimenti stai solo pubblicando un link e non offri nulla di costruttivo.
Levon,

Considera che c'è un \nnome in una directory che non puoi usare cut per recuperarlo (che è quello che stavi facendo quando ti ho sottovalutato). Ci sono alcuni casi in cui lsnon si comportano in modo pericoloso ed è quasi sempre più sicuro usare un altro modo.
Rahmu,

9

Usando GNU find, puoi usare -mindepth per evitare che find corrisponda alla directory corrente:

find . -type d -maxdepth 1 -mindepth 1

Dato che non lo stai facendo in modo ricorsivo, puoi usare un bash glob:

echo */

L'aggiunta di un finale / a un glob comporterà la corrispondenza solo delle directory.


1
*/manca i file punto e include collegamenti simbolici. Questo può o meno essere un problema.
Gilles 'SO- smetti di essere malvagio' il

@Gilles - Mancheranno sempre i collegamenti simbolici, ma i dotfile dipendono dal fatto che dotglob sia impostato o meno.
Giordania,

6

Lascia sedrimuovere quei due caratteri:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'

6

Preferirei usare:

 find ./ -type d -maxdepth 1 -exec basename {} \;

2

Di solito uso:

find * -type d

Ma non so se è il modo giusto di fare quello che vuoi.


1
Se hai intenzione di lasciare che la shell espanda tutti i nomi dei file, perché usare find?
Giordania,

@jordanm Per selezionare solo le directory. echo */farebbe la stessa cosa, più o meno (manca i file punto e include i collegamenti simbolici), ma Joachim chiederà come rimuovere il finale /.
Gilles 'SO- smetti di essere malvagio' il

0

In AIX il parametro 'maxdepth' non funziona.

In generale, questo funziona per me:

find ./ -type d | cut -d"/" -f2 | sort -u


0

Quello che stai cercando viene chiamato basename, ignora la struttura della directory di unix

Esempio sotto:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

escluderà per l'output anche il percorso dir, eliminando la necessità di cd eseguire prima il comando


Alcune informazioni aggiuntive:

Passerei -execcome argomento per trovare invece |(pipe) un altro comando per l'output (evitando che il secondo comando vada su ogni riga di output, detto che, a seconda dell'output, potrebbe migliorare le prestazioni dello script)

NOTA: le findopzioni non sono posizionali (-maxdepth influenza i test specificati prima e quelli specificati dopo).

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.