
de Linux find
commando is geweldig in het zoeken naar bestanden en mappen. Maar u kunt de resultaten van de zoekopdracht ook doorgeven aan andere programma’s voor verdere verwerking. Wij laten u zien hoe.
Het Linux-zoekcommando
de Linux find
commando is krachtig en flexibel. Het kan zoeken naar bestanden en mappen met behulp van een hele reeks verschillende criteria, niet alleen bestandsnamen. Het kan bijvoorbeeld zoeken naar lege bestanden, uitvoerbare bestanden of bestanden die eigendom zijn van een bepaalde gebruiker. Het kan bestanden vinden en weergeven op hun geopende of gewijzigde tijden, je kunt regex-patronen gebruiken, het is standaard recursief en het werkt met pseudo-bestanden zoals named pipes (FIFO-buffers).
Dat is allemaal fantastisch nuttig. de nederige find
commando pakt echt wat kracht in. Maar er is een manier om die kracht te benutten en dingen naar een ander niveau te tillen. Als we de uitvoer van de kunnen nemen find
commando en het automatisch gebruiken als invoer voor andere commando’s, kunnen we iets laten gebeuren met de bestanden en mappen die voor ons ontdekt worden.
Het principe van het pipen van de uitvoer van de ene opdracht naar een andere opdracht is een kernkenmerk van Unix-afgeleide besturingssystemen. Het ontwerpprincipe om een programma één ding te laten doen en het goed te laten doen, en te verwachten dat de uitvoer de invoer van een ander programma kan zijn – zelfs een nog ongeschreven programma – wordt vaak beschreven als de ‘Unix-filosofie’. En toch zijn er enkele kernhulpprogramma’s, zoals: mkdir
accepteer geen doorgesluisde invoer.
Om deze tekortkoming aan te pakken, xargs
commando kan worden gebruikt om doorgesluisde invoer te bundelen en in andere commando’s in te voeren alsof het commandoregelparameters zijn voor dat commando. Hiermee wordt bijna hetzelfde bereikt als eenvoudig leidingwerk. Dat is “bijna hetzelfde” en niet “exact hetzelfde” omdat er onverwachte verschillen kunnen zijn met shell-uitbreidingen en bestandsnaamglobbing.
Zoeken gebruiken met xargs
We kunnen gebruiken find
met xargs
tot een actie die wordt uitgevoerd op de gevonden bestanden. Dit is een omslachtige manier om dit aan te pakken, maar we kunnen de bestanden die zijn gevonden door find
naar binnen xargs
die ze vervolgens naar tar
om een archiefbestand van die bestanden te maken. We voeren deze opdracht uit in een map die veel PAGE-bestanden van het helpsysteem bevat.
find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz
De opdracht is opgebouwd uit verschillende elementen.
-
zoek ./ -naam “*.pagina” -type f -print0: De zoekactie start in de huidige map, waarbij op naam wordt gezocht naar bestanden die overeenkomen met de zoekreeks “*.page”. Directory’s worden niet weergegeven omdat we specifiek zeggen dat het alleen naar bestanden moet zoeken, met
-type f
. Deprint0
argument verteltfind
om witruimte niet te behandelen als het einde van een bestandsnaam. Dit betekent dat bestandsnamen met spaties correct worden verwerkt. -
xargs -o: De
-0
argumentenxargs
om witruimte niet te behandelen als het einde van een bestandsnaam. -
tar -cvzf page_files.tar.gz: Dit is het commando
xargs
gaat de bestandenlijst voeden vanfind
naar. Het tar-hulpprogramma maakt een archiefbestand aan met de naam “page_files.tar.gz”.
We kunnen gebruiken ls
om het archiefbestand te zien dat voor ons is aangemaakt.
ls *.gz
Het archiefbestand wordt voor ons aangemaakt. Om dit te laten werken, moeten alle bestandsnamen worden doorgegeven aan tar
massaal, wat is er gebeurd. Alle bestandsnamen zijn getagd op het einde van de tar
commando als een zeer lange commandoregel.
U kunt ervoor kiezen om de laatste opdracht op alle bestandsnamen tegelijk uit te voeren of één keer per bestandsnaam aan te roepen. We kunnen het verschil vrij gemakkelijk zien door de uitvoer van xargs
naar het hulpprogramma voor het tellen van regels en tekens wc
.
Dit commando pijpt alle bestandsnamen in wc
onmiddelijk. Effectief, xargs
bouwt een lange opdrachtregel voor wc
met elk van de bestandsnamen erin.
find . -name "*.page" -type f -print0 | xargs -0 wc
De regels, woorden en tekens voor elk bestand worden afgedrukt, samen met een totaal voor alle bestanden.
Als we gebruik maken van xarg
’s -I
(replace string) optie en definieer een vervangende string-token—in dit geval ” {}
“—het token wordt in de laatste opdracht vervangen door elke bestandsnaam om de beurt. Dit betekent wc
wordt herhaaldelijk aangeroepen, één keer voor elk bestand.
find . -name "*.page" -type f -print0 | xargs -0 -I "{}" wc "{}"
De output is niet mooi uitgelijnd. Elke aanroep van wc
werkt op een enkel bestand dus wc
heeft niets om de output mee af te stemmen. Elke regel uitvoer is een onafhankelijke regel tekst.
Omdat wc
kan alleen een totaal geven als het op meerdere bestanden tegelijk werkt, we krijgen de samenvattende statistieken niet.
De optie find -exec
De find
commando heeft een ingebouwde methode om externe programma’s aan te roepen om verdere verwerking uit te voeren op de bestandsnamen die het retourneert. De -exec
(uitvoeren) optie heeft een syntaxis die lijkt op, maar verschilt van de xargs
opdracht.
find . -name "*.page" -type f -exec wc -c "{}" ;
Dit telt de woorden in de overeenkomende bestanden. Het commando is opgebouwd uit deze elementen.
-
vinden .: Start het zoeken in de huidige directory. De
find
commando is standaard recursief, dus er wordt ook in submappen gezocht. - -naam “*.pagina”: We zijn op zoek naar bestanden met namen die overeenkomen met de zoekreeks “*.page”.
- -type f: We zoeken alleen naar bestanden, niet naar mappen.
-
-exec wc: We gaan de . uitvoeren
wc
commando op de bestandsnamen die overeenkomen met de zoekreeks. - -w: Alle opties die u aan de opdracht wilt doorgeven, moeten direct na de opdracht worden geplaatst.
- “{}”: De tijdelijke aanduiding “{}” vertegenwoordigt elke bestandsnaam en moet het laatste item in de parameterlijst zijn.
- ;: Een puntkomma “;” wordt gebruikt om het einde van de parameterlijst aan te geven. Het moet worden geëscaped met een backslash “”, zodat de shell het niet interpreteert.
Wanneer we die opdracht uitvoeren, zien we de uitvoer van wc
. De -c
(byte count) beperkt de uitvoer tot het aantal bytes in elk bestand.
Zoals je ziet is er geen totaal. De wc
opdracht wordt eenmaal per bestandsnaam uitgevoerd. Door een plusteken te vervangen “+
” voor de afsluitende puntkomma “;
” we kunnen veranderen -exec
’s gedrag om op alle bestanden tegelijk te werken.
find . -name "*.page" -type f -exec wc -c "{}" +
We krijgen de samenvatting van het totaal en netjes getabelleerde resultaten die ons vertellen dat alle bestanden zijn doorgegeven aan wc
als één lange opdrachtregel.
exec Betekent echt exec
De -exec
(execute) optie start de opdracht niet door deze in de huidige shell uit te voeren. Het gebruikt de ingebouwde exec van Linux om de opdracht uit te voeren, waarbij het huidige proces – je shell – wordt vervangen door de opdracht. Dus de opdracht die wordt gestart, wordt helemaal niet in een shell uitgevoerd. Zonder shell kun je geen shell-uitbreiding van wildcards krijgen en heb je geen toegang tot aliassen en shell-functies.
Deze computer heeft een gedefinieerde shell-functie genaamd words-only
. Dit telt alleen de woorden in een bestand.
function words-only () { wc -w $1 }
Een vreemde functie misschien, “words-only” is veel langer om te typen dan “wc -w”, maar het betekent in ieder geval dat u de opdrachtregelopties voor wc
. We kunnen testen wat het als volgt doet:
words-only user_commands.pages
Dat werkt prima met een normale opdrachtregelaanroep. Als we die functie proberen aan te roepen met find
’s -exec
optie, het zal mislukken.
find . -name "*.page" -type f -exec words-only "{}" ;
De find
commando kan de shell-functie niet vinden, en de -exec
actie mislukt.
Om dit te overwinnen kunnen we hebben find
start een Bash-shell en geef de rest van de opdrachtregel door als argumenten aan de shell. We moeten de opdrachtregel tussen dubbele aanhalingstekens plaatsen. Dit betekent dat we moeten ontsnappen aan de dubbele aanhalingstekens rond de “{}
” string vervangen.
Voordat we de . kunnen uitvoeren find
commando, moeten we onze shell-functie exporteren met de -f
(als functie) optie:
export -f words-only
find . -name "*.page" -type f -exec bash -c "words-only "{}"" ;
Dit loopt zoals verwacht.
De bestandsnaam meer dan eens gebruiken
Als u meerdere opdrachten aan elkaar wilt koppelen, kunt u dat doen en kunt u de “{}
” vervang string in elke opdracht.
find . -name "*.page" -type f -exec bash -c "basename "{}" && words-only "{}"" ;
Als wij cd
een niveau hoger uit de map “pages” en voer dat commando uit, find
zal de PAGE-bestanden nog steeds ontdekken omdat het recursief zoekt. De bestandsnaam en het pad worden doorgegeven aan onze words-only
functioneren als voorheen. Puur om redenen van het demonstreren van het gebruik van -exec
met twee commando’s noemen we ook de basename
commando om de naam van het bestand te zien zonder het pad.
Beide basename
commando en de words-only
shell-functie hebben de bestandsnamen aan hen doorgegeven met behulp van een “{}
” string vervangen.
Paarden voor cursussen
Er is een CPU-belasting en tijdstraf voor het herhaaldelijk aanroepen van een commando terwijl je het één keer zou kunnen aanroepen en alle bestandsnamen er in één keer aan zou kunnen doorgeven. En als je elke keer een nieuwe shell aanroept om het commando te starten, wordt die overhead erger.
Maar soms heb je – afhankelijk van wat je probeert te bereiken – geen andere optie. Welke methode uw situatie ook vereist, niemand zou verbaasd moeten zijn dat Linux voldoende opties biedt om degene te vinden die aan uw specifieke behoeften voldoet.