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
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 folosescfind
ș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.
xargs
ar putea fi, de asemenea, utilizate caxargs -I {} sh -c '...' sh {}
, dacă se dorește (face este posibil să executați lucrări paralele cu-P
dacă s-ar dori).