Să presupunem că vreau să găsesc toate fișierele .txt și să caut câteva șiruri. Aș face:

find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \; 

Ce se întâmplă dacă vreau să fac o filtrare mai complexă, astfel:

egrep something file.txt | egrep somethingelse | egrep other 

Inside find -exec? (sau similar)

Vă rog să rețineți că caut o soluție pe care să o pot scrie cu ușurință atunci când am nevoie de ea. Știu că acest lucru se poate face cu câteva linii folosind un script shell, dar asta nu este ceea ce caut.

Răspuns

Dacă trebuie să o faceți din interiorul căutării, trebuie să apelați un shell:

find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \; 

Alte alternative includ utilizarea xargs în schimb:

find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other 

Sau , mult mai sigur pentru numele de fișiere arbitrare (presupunând că find acceptă -print0):

find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other 

Sau, ați putea folosi doar o buclă de shell:

find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done 

Comentarii

  • Primul este exact ceea ce căutam. Extrem de simplu și suficient de mic pentru a tasta în funcție de nevoile mele. Mulțumim.
  • … și xargs ar putea fi, de asemenea, utilizate ca xargs -I {} sh -c '...' sh {}, dacă se dorește (face este posibil să executați lucrări paralele cu -P dacă s-ar dori).

Răspunde

Edit: Acest răspuns nu este preferat , dar este lăsat aici pentru comparare și ilustrare a capcanelor potențial periculoase în scriptarea bash.


Puteți pune bash (sau un alt shell) ca comandă -exec:

 find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;  

Unul dintre dezavantajele de a face acest lucru este că creează mai mult potențial pentru probleme de cotare imbricate pe măsură ce comenzile dvs. devin mai complexe. Dacă doriți să evitați acest lucru, îl puteți împărți într-un for -loop:

 for i in $(find -type -f -name "*.txt"); do if egrep -iH something "$i" | egrep somethingelse | egrep other; then echo "Found something: $i" fi done  

Comentarii

  • Primul este exact ceea ce căutam. Extrem de simplu și suficient de mic pentru a tasta în funcție de nevoile mele. Mulțumim.
  • Acea buclă for este o idee foarte proastă. Cunoscută și sub numele de bash pitfall # 1 .
  • Această "{}" din prima comandă poate duce chiar la injectarea de cod. Imaginați-vă că ați primit fișiere de la mine și ' este un fișier numit literal " & rm -rf ~ & : ".txt. Din fericire pentru dvs. -type -f este nevalid, tocmai a salvat directorul dvs. de acasă. Remediați greșeala de greșeală și încercați din nou. 🙂 terdon a făcut-o bine: find … -exec sh -c '… "$1" …' foo {} \;.
  • Vă mulțumim pentru informații! Da, -type -f este o greșeală de greșeală pe care o fac în mod constant atunci când folosesc find și nu am ' nu o observ în răspunsul meu. Hopa. Răspunsul terdon ' este mai bun, dar ' voi lăsa acest lucru în scopuri comparative.
  • @terdon: tx pentru a face referire la pagina mywiki.wooledge.org. Este ' plăcut să ai o grămadă de medici rezumați pe scurt într-un singur loc.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *