Jeg forstår, at -exec
kan tage en +
mulighed for at efterligne xargs
s opførsel. Er der nogen situation, hvor du “foretrækker en form frem for den anden?
Jeg personligt har en tendens til at foretrække den første form, hvis kun for at undgå at bruge et rør. Jeg regner med sikkerhed udviklerne af find
skal” have foretaget de passende optimeringer. Er jeg korrekt?
Svar
Du vil muligvis kæde opkald for at finde (en gang, når du fik at vide, at det er muligt , som måske er i dag). Dette er naturligvis kun muligt, så længe du bliver i find. Når du rør til xargs, er den uden for omfanget.
Lille eksempel, to filer a.lst og b.lst:
cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh
Intet trick her – simpelthen det faktum, at begge indeholder “fuddel”, men kun en indeholder “fiddel”.
Antag, at vi ikke vidste det. Vi søger i en fil, der matcher 2 betingelser:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls 192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Nå, måske kender du syntaksen for grep eller et andet program for at videregive begge strenge som betingelse, men at ” s ikke pointen. Hvert program, der kan returnere sandt eller falsk, givet en fil som argument, kan bruges her – grep var bare et populært eksempel.
Og bemærk, du kan følge find -exec med andre findkommandoer, som -ls eller -delete eller lignende. Bemærk, at sletning gør ikke kun rm (fjerner filer), men rmdir (fjerner mapper) også.
En sådan kæde læses som en AND-kombination af kommandoer, så længe ikke andet er angivet (nemlig med en -or
switch (og parens (som skal maskeres)).
Så du forlader ikke find-kæden, hvilket er en praktisk ting. Jeg kan ikke se nogen fordel ved at bruge -xargs, da du skal være forsigtig med at videresende filerne, hvilket er noget, der ikke er nødvendigt at gøre – det håndterer automatisk at sende hver fil som et enkelt argument for dig.
Hvis du mener, at du har brug for maskering til fund {} seler , er du velkommen til at besøge mit spørgsmål, der beder om beviser. Min påstand er: Du behøver ikke.
Kommentarer
Svar
Piping af filnavne sikkert til xargs
kræver, at din find
understøtter -print0
mulighed og din xargs
har den tilsvarende mulighed for at læse den (--null
eller -0
). Ellers filnavne med unprintab le tegn eller tilbageslag eller anførselstegn eller mellemrum i navnet kan forårsage uventet opførsel. På den anden side er find -exec {} +
i POSIX find
spec , så det er bærbart, og det er omtrent lige så sikkert som find -print0 | xargs -0
, og bestemt mere sikkert end find | xargs
. Jeg vil anbefale aldrig at gøre find | xargs
uden -print0
.
Kommentarer
- En bemærkelsesværdig undtagelse fra bærbarheden af
find … -exec … {} +
er OpenBSD, som kun erhvervede denne funktion med version 5.1 udgivet i 2012. Alle BSDer har haft-print0
i flere år, selv OpenBSD (selvom det også modstod denne funktion i et stykke tid). Solaris holder sig derimod til POSIX-funktioner, så du får-exec +
og ingen-print0
. -
-print0
er en smerte, og selvom du kan argumenterexargs --delimiter "\n"
isn ‘ t ækvivalent, jeg ‘ har aldrig brugt førstnævnte efter at have opdaget sidstnævnte . - Jeg kan ikke ‘ ikke se, hvordan
-0
er mere smertefuld end--delimiter "\n"
. - Ud over
-0
, GNUxargs
har brug for-r
for at undgå at køre kommandoen, hvis der ‘ ikke er input. - Et andet problem med
| xargs -r0 cmd
er, atcmd
‘ s stdin påvirkes (afhængigt afxargs
implementeringen er det ‘ s/dev/null
eller røret.
Svar
Hvis du bruger formen -exec ... ;
(husk for at undslippe semikolonet) kører du kommandoen en gang pr. filnavn. Hvis du bruger -print0 | xargs -0
, kører du flere kommandoer pr. filnavn. Du bør bestemt bruge -exec +
form, som placerer flere filer i en enkelt kommandolinje og er meget hurtigere, når et stort antal filer er involveret.
Et stort plus ved at bruge xargs
er evnen til at køre flere kommandoer parallelt ved hjælp af xargs -P
. På multi-core-systemer kan det give enorme tidsbesparelser.
Kommentarer
- Du mente
-P
i stedet for-p
. Husk, atxargs -P
ikke er i POSIX-standarden, mensfind -exec {} +
er, hvilket er vigtigt, hvis du går efter bærbarhed. - @Alexios Du behøver ikke ‘ undslippe plustegnet, fordi det ikke har en særlig betydning for skallen:
find /tmp/ -exec ls "{}" +
fungerer fint. - Corrent, selvfølgelig. Jeg ‘ har været ved at undslippe alt efter
-exec
så længe (jeg ‘ en masochist , Jeg bruger ikke ‘ ikke engang citater for at undslippe{}
, jeg skriver altid\{\}
; don ‘ t spørg), alt ser ud som om det skal undslippes nu. - @Alexios: Hvis du finder et eksempel (bortset fra at være en masochist) hvor maskering af seler er nyttigt, bedes du give det som svar på mit spørgsmål her – afaik dette tip er forældet og kun en relik på manpage. Jeg ‘ har aldrig set et eksempel, hvor
find /tmp/ -exec ls {} +
ikke ville ‘ t arbejde. - For mig er dette muskelhukommelse dannet i dagene af SunOS 4. Da jeg ‘ har gjort det i årevis, har jeg fuldstændig undladt at bemærke, hvornår
bash
begyndte at acceptere seler ordret. Jeg ‘ er ret sikker på, at mindst en af de gamle skaller, jeg ‘ har brugt, kastede hissy fit, hvis selerne var ‘ t undslap.
Svar
Med hensyn til ydeevne troede jeg, at -exec … +
ville simpelthen være bedre, fordi det “er et enkelt værktøj, der gør alt arbejdet, men , en del af GNU findutils dokumentation siger, at -exec … +
kan være mindre effektiv i nogle tilfælde:
[find med
-exec … +
] kan være mindre effektiv end nogle anvendelser afxargs
; for eksempelxargs
tillader, at der bygges nye kommandolinjer, mens den forrige kommando stadig udføres, og giver dig mulighed for at specificere et antal kommandoer, der skal køres parallelt.find ... -exec ... +
-konstruktionen har dog fordelen ved bred bærbarhed. GNU findutils understøttede ikke-exec ... +
indtil version 4.2.12 [januar 2005] ; en af grundene til dette er, at den under alle omstændigheder allerede havde handlingen ‘-print0
.
Jeg var ikke helt sikker på, hvad det betød, så jeg spurgte i chatten, hvor derobert forklarede det som:
find
sandsynligvis kunne fortsætte med at søge efter den næste batch af filer, mens-exec … +
kører, men det gør det ikke.
find … | xargs …
gør det, for så er fundet en anden proces, og det holder kører indtil rørbufferen fyldes op
(Formatering af mig.)
Så der er det. Men hvis ydeevne virkelig betyder noget, ville du være nødt til at foretage realistisk benchmarking eller rettere endda spørge dig selv, om du overhovedet vil bruge shell til sådanne tilfælde.
Her på dette site synes jeg det er bedre at råde folk til at brug formen -exec … +
, når det er muligt, fordi bare fordi det er enklere og af de grunde, der er nævnt i de andre svar her (f.eks. håndtering af mærkelige filnavne uden at skulle tænke meget).
-exec
måde at gøre så tre af fire kerner ikke ‘ ikke forbliver inaktiv?