Come escludere / ignorare file e directory nascosti in una ricerca "trova" con caratteri jolly?


119

A partire da (notare i caratteri jolly prima e dopo "un po 'di testo")

find . -type f -name '*some text*'

come si possono escludere / ignorare tutti i file e le directory nascosti?

Ho già cercato su Google per troppo tempo , mi sono imbattuto in qualche prugna e! (punto esclamativo) parametri, ma nessun esempio appropriato (e parsimonioso) che ha appena funzionato .

Effettuare il piping | su grepsarebbe un'opzione e accetterei anche con favore esempi di ciò; ma principalmente mi interessa un breve one-liner (o un paio di one-liner indipendenti, che illustrano modi diversi per raggiungere lo stesso obiettivo da riga di comando) semplicemente usando find.

ps: trovare file in linux ed escludere directory specifiche sembra strettamente correlato, ma a) non è ancora accettato eb) è correlato ma diverso e distinto, ma c) può fornire ispirazione e aiutare a individuare la confusione!

modificare

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", lavori. Il regex cerca "qualsiasi cosa, quindi una barra, quindi un punto, quindi qualsiasi cosa" (ovvero tutti i file e le cartelle nascosti, comprese le relative sottocartelle), e il "!" nega la regex.


Non aiuta con quello che hai chiesto nella tua modifica, ma dai un'occhiata alla mia domanda e alla sua risposta qui: unix.stackexchange.com/q/69164/15760 e anche il link nella risposta.

Risposte:


134

Questo stampa tutti i file che discendono dalla tua directory, saltando i file e le directory nascosti:

find . -not -path '*/\.*'

Quindi se stai cercando un file con il some textsuo nome e vuoi saltare file e directory nascosti, esegui:

find . -not -path '*/\.*' -type f -name '*some text*'

Spiegazione:

L' -pathopzione esegue un modello su tutta la stringa del percorso. *è un carattere jolly, /è un separatore di directory, \.è un punto (deve essere evitato per evitare un significato speciale) ed *è un altro carattere jolly. -notsignifica che non selezionare i file che corrispondono a questo test.

Non penso che findsia abbastanza intelligente da evitare la ricerca ricorsiva di directory nascoste nel comando precedente, quindi se hai bisogno di velocità, usa -pruneinvece, in questo modo:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print

Nota con l'ultimo che ti serve -printalla fine! Inoltre, non sono sicuro se -name '\.*' would be more efficient instead of -path` (perché il percorso sta cercando sottotracciati, ma questi verranno eliminati)
artfulrobot

Qual è il significato speciale di .in questo contesto?
Frostschutz,

@frostschutz Il punto dopo findindica la directory corrente: findesaminerà tutti i file e le directory nella directory corrente. L'argomento successivo pathè un'espressione regolare, in cui un punto normalmente significherebbe "qualsiasi carattere", per far sì che significhi un punto letterale, dobbiamo evitarlo con una barra rovesciata. L'argomento dopo -name non è un'espressione regolare, ma espande i caratteri jolly come ?e *come fa una shell.
Flimm,

2
@frostschutz In realtà, vieni a pensarci bene, potrei sbagliarmi sull'avere .un significato speciale.
Flimm,

1
@Flimm yup, non c'è bisogno di scappare .. Per quanto io sappia, solo questi devono essere sfuggito: *, ?, e [].
thdoan

10

Questo è uno dei pochi mezzi per escludere i file dot che funziona correttamente anche su BSD, Mac e Linux:

find "$PWD" -name ".*" -prune -o -print
  • $PWD stampa il percorso completo nella directory corrente in modo che il percorso non inizi con ./
  • -name ".*" -prune corrisponde a tutti i file o directory che iniziano con un punto e quindi non scendono
  • -o -printsignifica stampare il nome del file se l'espressione precedente non corrisponde a nulla. L'uso -printo -print0fa sì che tutte le altre espressioni non vengano stampate per impostazione predefinita.

Spiegare / elaborare "allarmantemente complicato"; le risposte già fornite e la tua risposta sembra dare prova del contrario ...?
pazzo per il natty

2
"allarmantemente complicato" è probabilmente eccessivo. Ho riformulato la risposta per arrivare al punto. Penso che la risposta che ho pubblicato sia difficile da capire ed è difficile da vedere senza una lettura molto attenta della pagina man. Se si sta solo utilizzando GNU trovare poi ci sono soluzioni più possibili.
Eradman,

-o ... -printè utile Per il mio uso, ora ho find ... '!' -name . -name '.*' -prune -o ... -print, che era più conveniente che includere $ PWD.
Roger Pate,

4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Esclude tutte le directory nascoste e i file nascosti in $ DIR


Questa è la risposta perfetta Trova ricorsivamente tutti i file ma esclude gli elementi pubblicitari per directory e file nascosti. Grazie!
KyleFarris,

2

La risposta che ho pubblicato inizialmente come "modifica" alla mia domanda originale sopra:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", lavori. Il regex cerca "qualsiasi cosa, quindi una barra, quindi un punto, quindi qualsiasi cosa" (ovvero tutti i file e le cartelle nascosti, comprese le relative sottocartelle), e il "!" nega la regex.


Simile, ma solo per la cartella corrente:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt

2

Non devi usarlo findper quello. Usa globstar in shell stesso, come:

echo **/*foo*

o:

ls **/*foo*

dove **/rappresenta qualsiasi cartella ricorsivamente e *foo*qualsiasi file che ha il foosuo nome.

Per impostazione predefinita, utilizzando lsverranno stampati i nomi dei file, esclusi i file e le directory nascosti.

Se non hai abilitato il globbing, fallo da shopt -s globstar.

Nota: una nuova opzione globbing funziona in Bash 4, zsh e shell simili.


Esempio:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden

5
Non ne hai bisogno ls! echo **/*foo*
Kevin Cox,

@kenorb (e @ kevin-cox). Potresti essere un po 'più prolisso? Perché globstar (= *) dovrebbe funzionare qui e come? Cosa fa la barra / fare?
pazzo per il natty del

@nuttyaboutnatty /significa cartella, separa le directory dal nome del file. *in sostanza rappresenta tutto.
Kenorb,

@kenorb yes-but: in che modo questo one-liner aiuta con la domanda originale?
pazzo per il natty del

1
@nuttyaboutnatty Esempio chiarito e aggiunto. Aiuta a trovare i file ignorando quello nascosto.
Kenorb,

1

La risposta di @ Flimm è buona, soprattutto perché impedisce che il ritrovamento scenda in directory nascoste . Preferisco questa semplificazione:

Generalmente per escludere tutti i percorsi nascosti (file regolari, directory, ecc.):

find <start-point> -path '*/.*' -prune -o <expression> -print

Ad esempio, utilizzando la directory di lavoro come punto iniziale e -name '*some text*'come espressione:

find . -path '*/.*' -prune -o -name '*some text*' -print

Contrariamente a quanto suggerisce la risposta di @ Flimm, nessun caso o file nascosti è il caso semplice. L' -path '*/.*'espressione è vero per qualsiasi percorso (file regolari, directory, ecc) che ha una .subito dopo l'separatore di file /. Quindi questa linea eliminerà sia i file che le directory nascoste.

Consentire i file nascosti escludendo le directory nascoste è il caso che richiede un ulteriore filtro. È qui che dovresti includere -type dl'espressione da potare.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Per esempio:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

In questo caso -type d -path '*/.*'è truesolo per le directory, quindi vengono eliminate solo le directory.


0

findha interruttori logici accurati come -ande -notpuoi usarli a tuo vantaggio per trovare un file corrispondente con due regole in questo modo:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Come puoi vedere, findusa due regole -name '*hidden_file*'e -and \( -not -name ".*" \)trova quei nomi di file che soddisfano entrambe le condizioni - nome file con hidden_filedentro ma senza punto iniziale. Nota le barre davanti alla parentesi: sono usate per definire le parentesi come findargomenti piuttosto che definire una sottostruttura (che è ciò che significa parentesi altrimenti senza barre)


0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Appunti:

  • . : cartella corrente
  • rimuovi -maxdepth 1per cercare ricorsivamente
  • -type f: trova i file, non le directory ( d)
  • -not -path '*/\.*' : non tornare .hidden_files
  • sed 's/^\.\///g': rimuove l'elemento anteposto ./dall'elenco dei risultati
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.