Piping da una scoperta a grep


8

Cosa sto cercando di fare?

Scrivi un comando che cerca tutti i file che non sono richiesti da nessun altro file nel mio progetto.

Che cosa ho provato?

Sto usando findper ottenere un elenco di nomi di file. Ora voglio usare i nomi dei file come stringa di ricerca (piuttosto che il file da cercare).

Sto usando find server/lib -type f -exec basename {} \; | cut -f 1 -d '.'per ottenere il mio elenco di nomi di file e rimuovere l'estensione del file.

Ora so che questo grep -R --exclude-dir=node_modules <search-string> . -lè ciò in cui voglio inserire ogni nome di file, ma non so come passarli come <search-string>argomento.


Altre informazioni

Sono anche vagamente consapevole che il piping a questo greppotrebbe passare l'intero risultato find(l'intero elenco di file) che ovviamente non voglio fare se questo è quello che sto per fare, allora dimmelo.

Inoltre, (anche se questo probabilmente non rientra nell'ambito di questa domanda) poiché sto usando questo come un modo per trovare uno dei nomi di file che grepnon riescono a trovare qualcosa per cui, qualsiasi consiglio su come ottenere questo tipo di output sarebbe molto apprezzato

> <the-command>

filename1
server/lib/foo.js # where these are the list of files in which it appears
test/lib/foo.js

filename2
Not Found! #where `filename2` wasn't found anywhere (obviously)

Risposte:


2

Risposta breve:

Se vuoi solo passare un mucchio di righe come argomenti a un altro comando, xargsè tuo amico - in questo caso, poiché lo stai mettendo nel mezzo di un comando, ti consigliamo di utilizzare la -I {}bandiera. Questo imposta {}come segnaposto in modo da poterlo posizionare ovunque (puoi impostare il tuo segnaposto, ma di solito mi attengo a{} poiché non verrà scambiato per molte altre cose.

Mettendo tutto insieme (supponendo che i comandi che hai dato facciano quello che pensi che facciano!):

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} grep -R --exclude-dir=node_modules {} . -l

Risposta lunga

Ok, quindi possiamo probabilmente andare oltre. Diciamo che volevi il formato che hai menzionato in precedenza - puoi xargsfarlo in sh -cmodo da poter concatenare i comandi:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l"

Eseguendo questo sul mio computer, sembra che questo ti stia dando i file in cui si trova il file . Il mio cervello è stanco, quindi invece di avvolgerlo in un bel copione (che è quello che dovresti effettivamente fare quando gli oneliners iniziano a diventare nodosi e usare https://www.shellcheck.net/ mentre ci sei) puoi invece hai questo orribile hack, che (penso) ti darà l'output che stai cercando:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l && printf \"\n\" || printf \"Not found\n\n\""


Grazie mille, sì, xargs -I {}è quello che stavo cercando.
Simon Legg,

6

Con zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/globbing ricorsivo. Una funzionalità introdotta zshnei primi anni '90.
  • (D.:t:r)è un qualificatore glob, una zshcaratteristica specifica che consente di selezionare i file utilizzando attributi diversi dal nome, oppure di cambiare l'ordinamento o apportare modifiche ai file trovati.
  • D: include dot-file e attraversa dot-dirs come findfarebbe. Molto probabilmente, ti consigliamo di toglierlo.
  • .: solo file regolari (come -type fin find)
  • :t, :r: modificatori di cronologia come in csh/ bashma qui applicati ai file globbed. :tper la coda (basename), :rper il nome radice (estensione rimossa).
  • x${^array}distribuisce gli elementi come rc's x^$arrayo fishs' x$arrayavrebbe fatto. Ad esempio se $arrayè ( 1, 2). Questo diventa x1 x2.
  • ${(u)array}(per unique), rimuovere i duplicati ( (u)essendo un flag di espansione dei parametri).

Per l'elenco dei file che non contengono nessuna stringa, sostituiscilo -lcon -L(supponendo GNU grep, ma qui stai già utilizzando opzioni specifiche GNU). -Fè per la ricerca di stringhe fisse (poiché probabilmente non si desidera che quei nomi di progetto vengano trattati come regexps). Potresti anche voler inserire -wun'opzione grepper la corrispondenza delle parole in modo che foonon corrisponda foobarper esempio (comunque corrisponderebbe foo-barcomunque).


Incredibile grazie per questo e le spiegazioni, non ero a conoscenza della projects=(server/lib/**/*(D.:t:r))produzione di un array come quello in zsh. Tuttavia ora ho bisogno di elencare i file in cui grepnon è stato possibile trovare nulla. Immagino che dovrei prendere un codice di uscita 0 / false?
Simon Legg,

@Simon, vedi la parte -Lalla fine della risposta
Stéphane Chazelas,

Sì, l'ho visto. -lmi dice dove era il risultato della ricerca e -Lmi dice dove non è stato trovato. Ma voglio sapere un elenco dei termini di ricerca che non sono stati trovati da nessuna parte piuttosto che dove sono stati / non sono stati trovati
Simon Legg
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.