Am'm încercarea de a rula un "găsi" comanda pentru toate fișierele JavaScript, dar cum nu am exclude un anumit director?
Aici este "găsi" cod're folosind.
for file in $(find . -name '*.js')
do
java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
Folosi -prune
comutator. De exemplu, dacă doriți să excludeți misc
director trebuie doar să adăugați o -cale ./misc-prune -o
să-ți găsi comanda:
find . -path ./misc -prune -o -name '*.txt' -print
Aici este un exemplu cu mai multe directoare:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
Aici excludem dir1, dir2 și dir3, deoarece, în "găsi" expresii este o acțiune care acționează pe criterii -calea dir1 -o-cale dir2 -o-cale dir3
(dacă dir1 sau dir2 sau dir3), e-a poruncit cu tip -d`.
O altă acțiune este `-o de imprimare, de imprimare.
Am găsit următoarele ușor de a raționa decât alte soluții propuse:
find build -not \( -path build/external -prune \) -name \*.js
# you can also exclude multiple paths
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js
Notă importantă: căile ce tastați după -calea
trebuie să se potrivească exact ceea ce "găsește" s-ar imprima fără excludere. Dacă această teză confundă doar asigurați-vă că pentru a utiliza pe deplin căi prin tot comanda astfel:
În interiorul \(
și \)
este o expresie care se va potrivi exact construi/extern
(vezi notă importantă mai sus), și, pe succes, avoid traversează nimic below. Acest lucru este atunci grupate ca o singură expresie cu a scăpat paranteză, și prefixate cu "- nu", care va face "găsi" săriți peste ceva care a fost însoțită de expresia asta.
S-ar putea întreba dacă adăugarea "- nu " nu va face toate celelalte fișiere ascunse de-prunereapar, iar răspunsul este nu. Apropo
-prune de lucrări este acel ceva care, odată ce este atins, fișierele de mai jos, care director permanent sunt ignorate.
Acest lucru vine de la un adevărat caz de utilizare, în cazul în care am nevoie pentru a apela yui-compresor pe unele fișiere generate de mayhew, dar lasă deoparte alte fișiere care trebuie să fie trimise ca-este.
Nota [1]: Dacă doriți să excludeți /tmp/foo/bar și vă rula ca acest "
find /tmp (..." apoi, trebuie să specificați
-calea /tmp/foo/bar. Dacă, pe de altă parte, de a alerga ca asta
cd /tmp; găsi . \ (...", "apoi, trebuie să specificați -cale ./foo/bar
.
Există în mod clar o confuzie aici ca de ce a preferat sintaxa pentru sărind peste un director ar trebui să fie.
GNU Aviz
To ignore a directory and the files under it, use -prune
Raționament
-prune se oprește "găsi" la coborârea într-un director. Doar specificarea
-nu -caleava mai coborî în *omit* director, dar-nu -calea
va fi falsă ori de câte ori "găsi" teste fiecare fișier.
Probleme cu-prune`
-prune
, ceea ce nu's destinate, dar sunt unele lucruri care trebuie să aibă grijă de când folosind-o.
-prune
funcționează numai cu -print
și nu alte acțiuni.-prune
funcționează cu orice acțiune, cu excepția -delete
. De ce nu't a lucra cu delete? Pentru a șterge la muncă, găsesc are nevoie pentru a traversa director în DFS comanda, din -delete va șterge mai întâi frunzele, apoi părinții de frunze, etc... Dar pentru specificarea
-prunepentru a face sens, "găsi" are nevoie de un director și de a opri descendent, care în mod clar nu are nici un sens cu profunzime " sau " - delete
pe.Performanță
Am înființat un test simplu din primele trei upvoted răspunsuri la această întrebare (înlocuit -print " cu " - exec bash -c 'echo $0' {} \;
pentru a arăta o altă acțiune, de exemplu). Rezultatele sunt mai jos
----------------------------------------------
# of files/dirs in level one directories
.performance_test/prune_me 702702
.performance_test/other 2
----------------------------------------------
> find ".performance_test" -path ".performance_test/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 23513814
> find ".performance_test" -not \( -path ".performance_test/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 10670141
> find ".performance_test" -not -path ".performance_test/prune_me*" -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files] 3 [Runtime(ns)] 864843145
Concluzie
Ambele f10bit's sintaxa și Daniel C. Sobral's sintaxa a luat 10-25ms pentru a rula pe medie. GetFree's sintaxa, care nu't folosi -prune
, a luat 865ms. Deci, da, acesta este mai degrabă un exemplu extrem, dar dacă îți pasă de timp a alerga și de a face ceva intensivă ar trebui să utilizați -prune
.
Nota Daniel C. Sobral's sintaxa a efectuat mai bine de două -prune
sintaxe; dar, bănuiesc că acest lucru este rezultatul unor caching ca trecerea ordinea în care cele două fugit dus la rezultatul opus, în timp ce non-prune versiune a fost întotdeauna mai lent.
Script De Test
#!/bin/bash
dir='.performance_test'
setup() {
mkdir "$dir" || exit 1
mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
"$dir/other"
find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
touch "$dir/other/foo"
}
cleanup() {
rm -rf "$dir"
}
stats() {
for file in "$dir"/*; do
if [[ -d "$file" ]]; then
count=$(find "$file" | wc -l)
printf "%-30s %-10s\n" "$file" "$count"
fi
done
}
name1() {
find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
}
name2() {
find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
}
name3() {
find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo "$0"' {} \;
}
printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"
printf "\nRunning performance test...\n\n"
echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\' {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf " [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"
echo \> find \""$dir"\" -not \\\( -path \""$dir/prune_me"\" -prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf " [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"
echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf " [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"
echo "Cleaning up test files..."
cleanup
Acesta este format am folosit pentru a exclude unele căi:
$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"
Am folosit acest lucru pentru a găsi toate fișierele nu în ".*" căi:
$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
-prune cu siguranță funcționează și este cel mai bun răspuns pentru că împiedică coborârea în dir care doriți să le excludeți.
-nu -calea` care încă mai caută excluse dir, doar nu - 't imprima rezultatul, care ar putea fi o problemă, dacă au fost excluse dir este montat rețeaua de volum sau tu nu't permisiuni.
Partea dificilă este că "găsi" este foarte special, despre ordinea de argumente, deci, dacă nu't le faci cum trebuie, comanda dvs. poate să nu funcționeze. Ordinea argumentelor este, în general, astfel:
find {path} {options} {action}
{path}
: Pune toate calea legate argumente în primul rând, ca . -calea './dir1' -prune -o
{opțiuni}
: I au cel mai mare succes atunci când pune -numele, -iname, etc
ca ultima opțiune în acest grup. E. g. de tip f -iname '*.js'
{acțiune}
: Te'll doriți să adăugați -print
atunci când se utilizează -prune
Aici's un exemplu de lucru:
# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js
# search for *.js, exclude dir1
find . -path './dir1' -prune -o -type f -iname '*.js' -print
# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print
Pe -calea -prune abordare, de asemenea, funcționează cu metacaractere în cale. Aici este o găsim afirmația că va găsi directoare pentru un git server care deservesc mai multe git repositiories lăsând la git interne directoare:
find . -type d \
-not \( -path */objects -prune \) \
-not \( -path */branches -prune \) \
-not \( -path */refs -prune \) \
-not \( -path */logs -prune \) \
-not \( -path */.git -prune \) \
-not \( -path */info -prune \) \
-not \( -path */hooks -prune \)
Pentru a exclude mai multe directoare:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)
Pentru a adăuga directoare, se adaugă -o -calea "./dirname/*"
:
find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)
Dar poate că ar trebui să utilizați un expresie regulată, dacă există mai multe directoare pentru a exclude.
Există o mulțime de răspunsuri bune, mi-a luat ceva timp pentru a înțelege ceea ce fiecare element de comanda a fost și logica.
find . -path ./misc -prune -o -name '*.txt' -print
găsi va începe să găsească fișierele și directoarele din directorul curent, prin urmare găsi .
.
-O
opțiune reprezintă o logică SAU și separă două părți de comanda :
[ -path ./misc -prune ] OR [ -name '*.txt' -print ]
Orice director sau fișier, care este nu a ./misc director nu va trece primul test -cale ./misc
. Dar acestea vor fi testate pe cea de-a doua expresie. Dacă numele lor corespunde model *.txt
au tipărit, pentru că a -print
opțiune.
Când găsi atinge ./misc director, acest director îndeplinește numai prima expresie. Deci, - prune
opțiune va fi aplicat acesta. Acesta spune comandă de căutare pentru a nu explora acel director. Deci orice fișier sau director în ./misc nici nu va fi explorat de a găsi, nu va fi testat în a doua parte a expresiei și nu vor fi tipărite.
Pentru o soluție de lucru (testat pe Ubuntu 12.04 (Precise Pangolin))...
find ! -path "dir1" -iname "*.mp3"
va căuta fișierele MP3 din directorul curent si subdirectoarele cu excepția cazului în dir1 subfolder.
Utilizare:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
...pentru a exclude dir1 ȘI dir2
Puteți folosi prune opțiune pentru a realiza acest lucru. Ca de exemplu:
find ./ -path ./beta/* -prune -o -iname example.com -print
Sau invers grep "grep -v" opțiune:
find -iname example.com | grep -v beta
Puteți găsi instrucțiuni detaliate și exemple în Linux comanda find exclude directoarele de căutare.
un truc bun pentru a evita imprimarea tunși directoare este de a utiliza -print
(lucrări pentru exec
precum) după partea dreapta a -sau "după" - prune
. De exemplu, ...
find . -path "*/.*" -prune -or -iname "*.j2"
va imprima calea tuturor fișierelor sub directorul curent cu `.j2" extensia, sărind peste toate directoarele ascunse. Curat. Dar va, de asemenea, imprimați calea completă de fiecare director o sare, după cum sa menționat mai sus. Cu toate acestea, următoarele nu, ...
find . -path "*/.*" -prune -or -iname "*.j2" -print
pentru că în mod logic nu's a ascuns -și
după -iname
operator și înainte de imprimare. Aceasta se leagă la partea dreapta a -sau
clauza din cauza boolean ordinea operațiilor și asociativitatea. Dar doctorii spun că nu's a ascuns -print
dacă (sau oricare dintre rudele sale ... -print0
, etc) nu este specificată. Deci, de ce nu - 't partea stângă a -sau
de imprimare? Se pare că (și eu am't înțeleagă acest lucru de la prima mea lectură pagina de om), care este adevărat dacă acolo nu există nici o -print
-sau exec
ORIUNDE, caz în care, -imprimare este logic stropit în jurul valorii de, astfel încât totul devine tipărite. Dacă chiar și UN "print" -stil de operațiune este exprimat în orice clauza, toate cele ascunse logice cele dispărea și veți obține doar ceea ce ai specificat. Acum sincer, aș fi preferat să fie invers, dar apoi o "găsi" cu doar descriptiv operatorii ar se pare că nu fac nimic, deci cred ca este logic ca este. După cum sa menționat mai sus, acest lucru toate lucreaza, cu exec
la fel de bine, astfel încât următoarele dă un plin e la
listare pentru fiecare fișier cu extensia dorită, dar nu listare primul nivel de fiecare director ascuns, ...
find . -path "*/.*" -prune -or -iname "*.j2" -exec ls -la -- {} +
Pentru mine (si altii de pe acest thread), "găsi" sintaxa devine destul de baroc destul de repede, așa că am arunca mereu în paranteze pentru a face SIGUR că știu ce se leaga de ce, așa că, de obicei, a crea un macro de tip, capacitate și formă, toate aceste declarații ca ...
find . \( \( ... description of stuff to avoid ... \) -prune \) -or \
\( ... description of stuff I want to find ... [ -exec or -print] \)
L's greu să meargă greșit de constituire a lumii în două părți în acest fel. Sper că acest lucru ajută, deși pare puțin probabil ca cineva să citească până la 30+lea a răspunde și de a vota, dar se poate spera. :-)
-calea <excluded_path> -prune -o
opțiune. Nu includ un trailing " / " la sfârșitul exclusă calea.
Exemplu:
find / -calea /mnt -prune -o-numele "*libname-server-2.o*" -print
Pentru a utiliza în mod eficient "găsi" eu cred că este imperios necesar să avem o bună înțelegere a sistemului de fișiere structura de directoare. Pe calculatorul de acasa am multi-TB hard disk-uri, cu aproximativ jumătate din conținutul susținute folosind rsnapshot
(de exemplu, rsync
). Deși back-up pentru un fizic independente (duplicat) conduce, este montat sub sistemul de rădăcină (/
) director: /mnt/Backup/rsnapshot_backups/
:
/mnt/Backup/ └── rsnapshot_backups/ ă── oră.0/ ă── oră.1/ ă── ... ă── zi cu zi.0/ ă── zi cu zi.1/ ă── ... ă── săptămânal.0/ ă── săptămânal.1/ ă── ... ă── lunare.0/ ă── lunare.1/ └── ...
La /mnt/Backup/rsnapshot_backups/
director ocupă în prezent ~2.9 TB, cu ~60 de milioane de fișiere și foldere; pur și simplu traversează acest conținut are nevoie de timp:
``
Astfel, oricând am nevoie pentru a căuta un fișier de pe
/` (rădăcină) partiție, trebuie să se ocupe cu (evita dacă este posibil) traversează mea backup partitie. EXEMPLE
Printre abordat diferit sugerat în acest thread (https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command), mi se pare că căutările folosind răspunsul acceptat sunt mult mai repede-cu rezerve.
Soluție 1
Las's spun vreau să găsi fișierul de sistem libname-server-2.o, dar eu nu vreau pentru a căuta prin
rsnapshotbackup-uri. Pentru a găsi rapid un sistem de fișiere, utilizați exclude calea
/mnt(de exemplu, utilizarea
/mnt", nu "/mnt/ " sau " /mnt/Backup`, sau ...):
``
dată find / -calea /mnt -prune -o-numele "libname-server-2.o" -print /usr/lib/libname-server-2.o real 0m8.644s ## 8.6 sec <<< NOTĂ! utilizator 0m1.669s sys 0m2.466s
$ START="$(data +"%s")" && 2>/dev/null / -calea /mnt -prune -o \
-numele "libname-server-2.o" -imprimare; END="$(data +"%s")"; \
TIMP="$((END - START))"; printf 'comanda find luat %s sec\n' "$TIMP"
/usr/lib/libname-server-2.o
comanda find luat de 3 sec. # # ~3 sec <<< NOTĂ!
... afla ca fișier în doar câteva secunde, în timp ce aceasta ia ***mult*** mai (care apar la recurse prin toate "exclude" directoare):
dată find / -calea /mnt/ -prune -o-numele "libname-server-2.o" -print găsi: avertisment: -calea /mnt/ nu se va potrivi nimic pentru că se termină cu /. /usr/lib/libname-server-2.o real 33m10.658s ## 33 min 11 sec (~231-663x mai lent!) utilizator 1m43.142s sys 2m22.666s
$ START="$(data +"%s")" && 2>/dev/null / -calea /mnt/ -prune -o \
-numele "libname-server-2.o" -imprimare; END="$(data +"%s")"; \
TIMP="$((END - START))"; printf 'comanda find luat %s sec\n' "$TIMP"
/usr/lib/libname-server-2.o
comanda find luat 1775 sec ## 29.6 min
**Soluție 2** Altă soluție oferită în acest thread ([SO#4210042](https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command/)) efectuează, de asemenea, slab:
REZUMAT | CONCLUZII Utilizați abordare ilustrată în "Soluție 1"
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
de exemplu
... -path <excluded_path> -prune -o ...
/
la excluse cale, "găsi" comanda apoi recursiv intră (toate cele) /mnt/*
directoare-care în cazul meu, pentru că a /mnt/Backup/rsnapshot_backups/*
subdirectoare, în plus, include ~2.9 TB de fișiere pentru a căuta! De nu adăugarea unui sfârșit /
căutare ar trebui să completeze aproape imediat (în decurs de câteva secunde).
"Soluția 2" (... -nu -calea <exclude calea> ...
), de asemenea, pare a recursiv de căutare prin excluse directoare ... nu se întorc excluse meciuri, dar inutil consumatoare că timpul de căutare. *Căutarea în cadrul acestor rsnapshot
backup:*
Pentru a găsi un fișier într-unul din orar/zilnic/săptămânal/lunar rsnapshot
backup-uri):
``
$ START="$(data +"%s")" && 2>/dev/null /mnt/Backup/rsnapshot_backups/zi.0 -numele '04t8ugijrlkj.jpg'; END="$(data +"%s")"; TIMP="$((END - START))"; printf 'comanda find luat %s sec\n' "$TIMP"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
comanda find luat 312 sec ## 5.2 minute: în ciuda aparent rsnapshot dimensiune
**Cu excepția imbricate director:** Aici, vreau să excludă o imbricate director, de exemplu, /mnt/Vancouver/proiecte/ie/gheare/de date/*` atunci când caută la `/mnt/Vancouver/proiecte/`:
$ ora găsi . -iname 'test_file'
./ie/gheare/de date/test_file
./ie/gheare/test_file
0:01.97
$ ora găsi . -calea '/date' -prune -o-iname 'test_file*' -print
./ie/gheare/test_file
0:00.07
`` O parte: Adăugarea -print
la sfârșitul comanda suprimă imprimare a exclus director:
$ find / -calea /mnt -prune -o-numele "*libname-server-2.o*" /mnt /usr/lib/libname-server-2.o $ find / -calea /mnt -prune -o-numele "*libname-server-2.o*" -print /usr/lib/libname-server-2.o