GNU parallel en xargs. Voer meerdere exemplaren van een opdracht parallel uit met verschillende argumenten. Wees voorzichtig bij het gebruik van xargs. Zoek nu naar hele woorden

xargs- een hulpprogramma voor het genereren van een lijst met argumenten en het uitvoeren van een opdracht. Dat wil zeggen, met xargs kunt u elk commando met argumenten aanroepen. De xargs-opdracht bestaat uit twee componenten. Eerst moet u de bestanden opgeven die u interesseren. Ten tweede moet u de opdracht of het script opgeven dat u op elk van deze bestanden wilt toepassen.

xargs - splitst de invoerstroom in argumenten en geeft de uitvoering ervan door aan elk commando (standaard echo). Leest vanaf standaardinvoer of via pijp.

xargs-verwerkingsmodi voor inkomende gegevens

    Standaard is het argumentscheidingsteken elk witruimteteken: spatie, tab, verticale tab of nieuwe regel. Maar zoals in commandoshell je kunt "" of \ gebruiken om het splitsen van argumenten te voorkomen.

    Modus ingeschakeld door de parameter -L. Bijna identiek aan de vorige, behalve dat xargs onthoudt welk argument op welke regel staat. Bovendien, als de regel eindigt met een spatie of tab, volgende regel wordt beschouwd als een voortzetting van de huidige.

    Regel voor regel. Ingeschakeld bij gebruik van de optie -I of -0. In dit geval wordt de hele tekenreeks als één geheel argument beschouwd, ondanks spaties en tabs erin. Voor -I is het einde van de regel het teken "\n" en voor -0 het teken "\0"

    Voorbeeld: Zoek in /home/user1 naar alle bestanden waarvan de naam eindigt op ".txt" en kopieer deze naar een andere map. zoek /home/user1 -naam "*.txt" | xargs cp -av --target-directory=/home/backup/ --parents

    Zoek een exemplaar van de zin logon home in alle bestanden in de map /etc/samba. $ vind /etc/samba | xargs grep -ni "inloggen thuis"

    Verwijder de lijst met bestanden. Bestandspaden worden regel voor regel geschreven in het bestand delfiles.txt xargs rm< delfiles.txt

Er is veel geschreven over het hulpprogramma xargs - wat kan er nog meer worden geschreven? Maar als je, zoals ze zeggen, dieper graaft, blijkt dat veel publicaties alleen de basisbeginselen schetsen, maar het belangrijkste missen: ze leggen niet uit hoe xargs in de echte praktijk kunnen worden gebruikt. Artikelen waarin complexe en niet-triviale toepassingen hiervan worden geanalyseerd, zijn zeer nuttig systeembeheerder Helaas zijn er maar heel weinig hulpmiddelen. Daarom hebben we ons artikel geschreven en geprobeerd zoveel mogelijk voorbeelden op te nemen. gebruik van xargs om verschillende problemen op te lossen.

Eerst zullen we bekijken hoe xargs werkt en eenvoudigere voorbeelden analyseren, en vervolgens doorgaan met het analyseren van complexe en interessante gevallen.

Laten we de basis onthouden

De manier waarop xargs werkt kan als volgt worden beschreven: het programma haalt gegevens uit standaardinvoer of uit een bestand en splitst deze op basis van gespecificeerde parameters en geeft het vervolgens als argument door aan een ander programma.

IN algemeen beeld De xargs-opdrachtsyntaxis kan als volgt worden weergegeven:

[lijst_generator_command] | xargs [xargs_options] [opdracht]

Laten we eens kijken hoe het allemaal werkt met behulp van eenvoudige voorbeelden en schoolvoorbeelden.

Bestanden verwijderen

Een van de meest voorkomende situaties waarin xargs wordt gebruikt, is het verwijderen van bestanden die zijn gevonden met de opdracht find.

Laten we ons voorstellen de volgende situatie: er is een map waarin het is opgeslagen groot aantal bestanden. U moet er bestanden uit verwijderen bepaald type(in ons voorbeeld - bestanden met de extensie *.sh). Om deze bewerking uit te voeren, moet u de uitvoer van het find-commando doorgeven aan xargs, en het -rm-commando zal worden toegepast op bestanden met de opgegeven extensie:

$ ls één.sh één.py twee.sh twee.py $ zoek . -naam "*.sh"| xargs rm -rf $ ls one.py twee.py

Merk op dat de bewerking van het verwijderen van bestanden kan worden uitgevoerd zonder xargs, maar met behulp van de opdracht

$vind. -naam "*.sh" -exec rm -rf "()" \

De beschreven methode werkt niet als de naam van een van de te verwijderen bestanden een spatie bevat. Een naam die bestaat uit twee woorden, gescheiden door een spatie, wordt niet als één geheel geaccepteerd.

Laten we dit illustreren met het volgende voorbeeld:

$ ls nieuw bestand.sh one.sh one.py two.sh two.py $ find . -naam "*.sh"| xargs rm -rf $ ls nieuw bestand.sh one.py two.py

Zoals u kunt zien, is het bestand met een spatie in de naam niet verwijderd.

Om dit probleem op te lossen, gebruikt u de optie print0 voor de opdracht find en de optie -0 voor de opdracht xargs. Het vervangt het standaard scheidingsteken (regeleinde met een nulteken (\x0), wat het einde van de opgeslagen tekenreeks betekent:

$vind. -naam "*.sh" -print0 | xargs -0 rm -rf

Xargs kan bijvoorbeeld ook helpen om alles snel te verwijderen tijdelijke bestanden met tmp-extensie:

$ vind /tmp -naam "*.tmp"| xargs rm

Bestandscompressie

U kunt alle bestanden in de huidige map comprimeren met gzip door de volgende opdracht in te voeren:

$ls | xargs -p -l gzip

Laten we een ander voorbeeld bekijken: alle bestanden met de extensie *.pl comprimeren met tar:

$vind. -naam "*.pl" | xargs tar -zcf pl.tar.gz

Bestanden hernoemen

Met xargs kun je dat doen massaal hernoemen bestanden. Laten we ons voorstellen dat we een groep bestanden hebben met de extensie *.txt, en we moeten deze extensie vervangen door *.sql. Dit kan worden gedaan met behulp van xargs en tekststreaming sed-editor:

$ls | sed -e "p;s/.txt$/.sql/" | xargs-n2 fmv

Als gevolg van de uitvoering ervan wordt een lijst met hernoemde bestanden op de console weergegeven.

Met xargs kun je ook toevoegen aan aanvullende elementen naar bestandsnamen (bijvoorbeeld datum):

$ls | xargs -I BESTAND mv()<...>-{}

In plaats van<..>je kunt alles vervangen wat je wilt.
De accolades () in dit voorbeeld betekenen het "huidige argument" (d.w.z. de huidige bestandsnaam).

Machtigingen voor mappen en bestanden wijzigen

Met behulp van xargs kunt u ook het proces van het wijzigen van machtigingen voor bestanden en mappen versnellen specifieke gebruiker of groepen. Laten we zeggen dat we alle mappen moeten vinden root-gebruiker en hun eigenaar vervangen door uitzendkracht. Deze bewerking wordt uitgevoerd met behulp van het commando:

$vind. -groepswortel -print | xargs chown-temp

Om alle mappen van de hoofdgroep te vinden en de groep te vervangen door temp, gebruik je de opdracht:

$vind. -groepswortel -print | xargs chgrp-temp

Xargs en vondst: complexe operaties

U kunt complexere bewerkingen uitvoeren met de opdrachten find en xargs. Zo kunt u bijvoorbeeld tijdelijke bestanden verwijderen die meer dan zeven dagen geleden zijn aangemaakt:

$ find /tmp -type f -naam "*" -mtime +7 -print0 | xargs -0 rm -f

En hier leest u hoe u processen die al meer dan zeven dagen actief zijn, met geweld kunt stoppen:

$ find /proc -user myuser -max Depth 1 -type d -mtime +7 -exec basisnaam() \; | xargs doden -9

Xargs en knippen

Xargs wordt vaak gebruikt in combinatie met het commando knippen, waarmee je lijnen kunt knippen tekstbestanden. Laten we er een paar bekijken praktische voorbeelden. Met behulp van de onderstaande opdracht wordt een lijst met alle gebruikers op het systeem op de console weergegeven:

$ knippen -d: -f1< /etc/passwd | sort | xargs echo

En het team kijkt

Bestand * | grep ASCII | knippen -d: -f1 | xargs -p vim

zal bestanden opeenvolgend openen voor bewerking in vim.
Laten we aandacht besteden aan de optie -p. Dankzij dit wordt de opdracht uitgevoerd in interactieve modus: Bevestiging (j/n) wordt gevraagd voordat elk bestand wordt geopend.

Kortom, hier is nog een complex en interessant voorbeeld- recursief zoeken naar bestanden zelf groot formaat in een bepaalde map:

$vind. -type f -printf "%20s %p\n" | sorteer -n | knippen -b22- | tr "\n" "\000" | xargs -0 ls -laSr

Parallelle werking van processen

Xargs wordt vaak gebruikt om meerdere processen parallel uit te voeren. Zo kunt u bijvoorbeeld meerdere mappen tegelijk comprimeren in tar.gz:

$ echo map1 map2 map3 | xargs -P 3 -I NAAM tar czf NAAM.tar.gz NAAM

In het onderstaande voorbeeld wordt de schakelaar -P gebruikt. Hij wijst maximale hoeveelheid processen die gelijktijdig zullen plaatsvinden. Laten we aannemen dat we 10 argumenten als invoer hebben. Als we het commando xargs invoeren met de schakeloptie -P 3, worden er 3 exemplaren van het commando dat volgt op xargs gestart, met elk van deze argumenten.

Met xargs kunt u ook meerdere bestanden parallel downloaden van internet:

In het gegeven voorbeeld met opgegeven adres alles wordt gedownload grafische bestanden Met jpg-extensie; De schakelaar -P geeft aan dat u 10 bestanden tegelijk moet downloaden.

Voorlopige resultaten

Laten we de voorlopige resultaten samenvatten en een paar regels formuleren voor het werken met xargs.

  1. Xargs werkt niet met bestanden die een spatie in de naam hebben. Om dit probleem met de opdracht xargs op te lossen, gebruikt u de optie −0. U kunt de spatie in de bestandsnaam ook als volgt omzeilen: $ xargs -I FILE my_command “FILE”
  2. De opdracht xargs accepteert opdrachten van standaardinvoer, gescheiden door een spatie of nieuwe regel. Om deze opdrachten te groeperen, kunt u dubbel of gebruiken enkele aanhalingstekens. U kunt het scheidingsteken ook opgeven met de optie -d;
  3. Als er geen argumenten aan xargs worden doorgegeven, wordt het commando /bin/echo standaard uitgevoerd;
  4. In veel gevallen kan de opdracht xargs worden vervangen door een for-lus. Bijvoorbeeld de opdracht $find. -type f -en -iname "*.deb" | xargs -n 1 dpkg -I

    volledig gelijk aan de cyclus

    $ voor bestand bij 'vinden'. -type f -en -iname "*.deb"`; doe dpkg -I "$bestand"; klaar

Niet-triviale voorbeelden

We hebben de basis onthouden typische opties gebruik overwogen... Laten we nu verder gaan met meer complexe en niet-triviale voorbeelden. Een aantal ervan hebben we zelf bedacht, waarbij we aan alledaagse taken werkten, en sommige hebben we geleerd van de site http://www.commandlinefu.com (voor iedereen die de fijne kneepjes van het werken met opdrachtregel Wij raden u ten zeerste aan er af en toe een bezoek aan te brengen (u kunt daar soms zeer nuttig advies vinden).

Ban IP-adressen uit de lijst

Om IP-adressen uit de lijst te weren, moet u ze toevoegen aan IP-tabellen met de DROP-regel. Deze bewerking wordt uitgevoerd met behulp van het commando:

$ cat bad_ip_list | xargs -I IP iptables -A INPUT -s IP -j DROP

Je kunt meer doen complexe operatie en verbied alle adressen door AS:

$ /usr/bin/whois -H -h whois.ripe.net -T route -i oorsprong AS<номер>|egrep "^route"|awk "(print $2)" |xargs -I NET iptables -A INPUT -s NET -j DROP

Het URL-formaat wijzigen

U kunt een URL zoals 'http%3A%2F%2Fwww.google.com' converteren naar 'http://www,google.com' met behulp van de opdracht:

Echo "http%3A%2F%2Fwww.google.com" | sed -e"s/%\(\)/\\\\\x\1/g" | xargs echo -e

Een wachtwoord van 10 tekens genereren

Genereer sterk wachtwoord kan gedaan worden met een commando als:

$ tr -dc A-Za-z0-9_< /dev/urandom | head -c 10 | xargs

U kunt wachtwoorden genereren zonder de hulp van xargs: er is een gespecialiseerd hulpprogramma hiervoor, pwgen. Er worden ook enkele andere methoden voor het genereren van wachtwoorden beschreven.

Zoeken naar binaire bestanden die zijn geïnstalleerd zonder dpkg te gebruiken

Een dergelijke operatie kan nodig zijn als bijvoorbeeld de auto slachtoffer is geworden hacker aanval en er is malware op geïnstalleerd software. Het volgende commando helpt u te identificeren welke programma's de aanvallers hebben geïnstalleerd (het lijkt erop dat er “binaire bestanden” worden geïnstalleerd zonder gebruik te maken van de dpkg-pakketbeheerder):

$ cat /var/lib/dpkg/info/*.list > /tmp/listin ; ls /proc/*/exe |xargs -l leeslink | grep -xvFf /tmp/listin; rm /tmp/listin

Verouderde kernelpakketten verwijderen

$ dpkg -l linux-* | awk "/^ii/(print $2)" | grep -v -e `uname -r | knippen -f1,2 -d"-"` | grep -e | xargs sudo apt-get -y purge

Het probleem van het verwijderen van oude kernels is al besproken op Habré - zie (op dezelfde link kun je interessante voorbeelden van commando's vinden).

Het script converteren naar een string

Soms is het nodig om een ​​groot script in één regel om te zetten. Je kunt het als volgt doen:

$ (sed "s/#.*//g"|sed "/^ *$/d"|tr "\n" ";"|xargs echo)< script.sh

Conclusie

Zoals uit de recensie blijkt, zijn de mogelijkheden van xargs veel breder dan het op het eerste gezicht lijkt. We hopen dat de voorbeelden in dit artikel nuttig voor u zullen zijn. Als u andere interessante toepassingen voor xargs kent, welkom in de reacties.

Op lange winteravonden zat ik en dacht: "Als het daglicht komt, ga ik zitten en ga ik op de juiste manier om met dit mysterieuze xarg-hulpprogramma." Nou, het lijkt erop dat de tijd is gekomen - ik ging zitten om het uit te zoeken. Het eerste wat mij opviel was dat de man ervoor nogal mysterieus was en de zaken niet meteen duidelijk maakte. op Wikipedia voegde ook geen enkel inzicht toe, maar bracht mij zelfs in verwarring, dus besloot ik mijn eigen onderzoek uit te voeren en erover te schrijven kleine handleiding kleine jongen Zoals je weet, zul je het begrijpen als je het uitlegt :)

Dus, xargs.

xargs is een opdrachtregelhulpprogramma waarmee u elk commando kunt oproepen waarvan de argumenten zijn overgenomen standaard invoer. Bovendien kunnen de argumenten in één keer worden doorgegeven, of kunnen ze in verschillende stukken worden gegroepeerd. We zullen xargs versie 4.4.0 bestuderen, en volgens de aanbeveling van de man zullen we alleen nieuwe argumenten gebruiken die niet als verouderd zijn gemarkeerd (het is beter om meteen te wennen aan correct werken).

Het eerste dat u moet begrijpen, is dus hoe xargs de binnenkomende stroom verwerkt en in argumenten verdeelt. Er zijn verschillende modi, afhankelijk van de opties:

1. Normaal. Standaard is het argumentscheidingsteken elk witruimteteken: spatie, tab, verticale tab of nieuwe regel. Maar net als in de opdrachtshell kunt u "" of \ gebruiken om het splitsen van argumenten te voorkomen.

2. Regelmatig, met groepering. Modus ingeschakeld door de parameter -L. Bijna identiek aan de vorige, behalve dat xargs onthoudt welk argument op welke regel staat. Bovendien, als een regel eindigt met een spatie of tab, wordt de volgende regel beschouwd als een voortzetting van de huidige.

3. Regel voor regel. Ingeschakeld bij gebruik van de optie -I of -0. In dit geval wordt de hele tekenreeks als één geheel argument beschouwd, ondanks spaties en tabs erin. Voor -I is het einde van de regel het teken "\n" en voor -0 het teken "\0"

Laten we een paar tests doen om dit allemaal beter te begrijpen. Laten we een bestandstest maken met de volgende inhoud (== het is niet nodig om het bestand in te voeren):
==
arg1
arg2 spatie
"arg3 geciteerd"
arg4\ is ontsnapt
arg5 met
doorgaan
==
(Er moet een spatie staan ​​na "arg5 with")
We zullen ook een klein tp-script schrijven dat de argumenten zal uitvoeren, gescheiden door het symbool ":" en de hoeveelheid:
==
#!/bin/bash
echo -n "@$#"
terwijl [[ $1 != "" ]]; doe echo -n ":$1"; verschuiving; klaar
echo
==

Normale modus (argumenten selecteren door witruimte tekens):
x $ kattentest | xargs./tp
@8:arg1:arg2:spatie:arg3 geciteerd:arg4 ontsnapt:arg5:met:doorgaan
Het bestand werd opgesplitst in argumenten met behulp van witruimtetekens, maar de regels tussen aanhalingstekens en escape-tekens met het teken "\" bleven intact.

De normale modus met groeperen op rijen verschilt in dit stadium niet van de vorige.

Lijnsplitsing. Laten we een tweede testbestand maken met de volgende opdracht:
x $ cp test testz && printf "\0arg6" >> testz
Laten we het controleren
x $ kat testz | xargs -0 ./tp
@2:arg1
arg2 spatie
"arg3 geciteerd"
arg4\ is ontsnapt
arg5 met
doorgaan
:arg6

Zoals u kunt zien, zijn er slechts twee argumenten. De eerste is lang, met behoud van regeleinden, aanhalingstekens en \, en de tweede is arg6. In het bestand worden ze gescheiden door een null-teken.

Wat betreft de scheiding van parameters kan nog één ding worden gezegd over de optie -d, die een nieuw scheidingsteken specificeert. Laten we bijvoorbeeld '3' als scheidingsteken gebruiken.
x $ kattentest | xargs -d 3 ./tp
@2:arg1
arg2 spatie
"arg: geciteerd"
arg4\ is ontsnapt
arg5 met
doorgaan
Het bestand is opgedeeld in 2 delen op de plaats van het "3"-symbool. Het opmerkelijke is dat je op deze manier de optie -0 kunt emuleren
x $ kat testz | xargs -d "\x00" ./tp
@2:arg1
arg2 spatie
"arg3 geciteerd"
arg4\ is ontsnapt
arg5 met
doorgaan
:arg6

Het lijkt erop dat we de verdeling van de invoerstroom in argumenten hebben opgelost, laten we verder gaan met parametervervanging.

Dus na zijn opties wacht xarg op een commando dat het zal uitvoeren. Alle binnenkomende argumenten worden in groepen verdeeld, waarna opdracht gegeven wordt voor elke groep aangeroepen en alle argumenten uit die groep worden eraan doorgegeven.

Laten we nu eens kijken hoe groepen worden gevormd.

1. Als er geen opties zijn, dan is er maar één groep, alle argumenten uit de invoerstroom vallen daarin. Een groep van oneindige omvang, om zo te zeggen :)

2. De optie -L n specificeert groeperen op lijnen. Aan het commando worden argumenten doorgegeven op n regels. Ik zal het met voorbeelden demonstreren.
Groeperen op 1 regel:
x $ kattentest | xargs -L 1 ./tp
@1:arg1
@2:arg2:spatie
@1:arg3 geciteerd
@1:arg4 ontsnapt
@3:arg5:met:doorgaan
Je kunt zien dat de tweede regel 2 argumenten bevat, omdat ze allebei op dezelfde regel staan. En de laatste is eigenlijk 3, aangezien de voorlaatste regel “verlengd” is vanwege de ruimte aan het einde.

Groepeer nu op 2 regels. De opdracht bevat regels 1 en 2; 3 en 4; en wees 5e:
x $ kattentest | xargs -L 2 ./tp
@3:arg1:arg2:spatie
@2:arg3 geciteerd:arg4 is ontsnapt
@3:arg5:met:doorgaan

3. Groeperen op argumenten, gespecificeerd door de optie -n x. Alles is hier transparant: de argumenten worden gegroepeerd in x-stukken en doorgegeven aan de opdracht.
Voor één argument:
x $ kattentest | xargs -n 1 ./tp
@1:arg1
@1:arg2
@1: spatie
@1:arg3 geciteerd
@1:arg4 ontsnapt
@1:arg5
@1: met
@1: ga door
Elk 2 argumenten:
x $ kattentest | xargs -n 2 ./tp
@2:arg1:arg2
@2:spatie:arg3 geciteerd
@2:arg4 ontsnapt:arg5
@2:met:doorgaan

3. Vervangingsmodus - optie -I. Om te beginnen moeten we dat in herinnering brengen deze modus Argumenten uit de invoerstroom worden anders geparseerd. Elke regel is één geheel argument; regels worden niet aaneengeschakeld. Ten tweede heeft de optie -I een parameter: een string, die in de opdracht wordt vervangen door een argument:
x $ echo -e "A B\nC D" | xargs -I _ ./tp =_+_=
@1:=A B+A B=
@1:=C D+C D=
Het is gemakkelijk op te merken dat het teken _ is opgegeven als een argumentvervangingsreeks, die twee keer in de opdracht wordt gebruikt. U kunt ook zien dat de argumenten als hele regels worden toegewezen en dat de spatie geen invloed heeft op het parseren. Het commando wordt voor elk argument aangeroepen.

Dat is alles met vervanging. Laten we eens kijken naar de resterende belangrijke opties
-r - voer de opdracht niet uit als er geen argumenten zijn:
x $ cat /dev/null | xargs./tp
@0
x $ cat /dev/null | xargs -r./tp
x$
Zoals u kunt zien, werd de opdracht in het tweede geval niet uitgevoerd.

P - xargs zal om bevestiging vragen om elke opdracht uit te voeren.

Hiermee is de korte tutorial voltooid. Het bleek niet heel kort te zijn, maar ik hoop dat het begrijpelijk was;)

Vermijd slechte UNIX-praktijken

Vaak raken we, met welk systeem dan ook, gewend aan bepaalde werkpatronen. Maar deze sjablonen zijn niet altijd optimaal. Soms ontwikkelen we zelfs slechte gewoonten die tot rommel en onhandigheid op het werk leiden. Een van de beste manieren Door dergelijke tekortkomingen te corrigeren, ontwikkel je de gewoonte om goede technieken te gebruiken die rommel voorkomen. Dit artikel biedt 10 methoden om met teamwerk te werken UNIX-reeks waardevolle gewoonten die u zullen helpen veel voorkomende tekortkomingen te vermijden en uw werkefficiëntie te verbeteren. Gedetailleerde beschrijving Elk van de methoden wordt na de lijst gegeven.

Laten we 10 goede gewoonten leren

Tien goede methoden om aan te wennen:

Maak directorystructuren met één opdracht

Lijst 1 illustreert een van de meest voorkomende UNIX-fouten: het stap voor stap specificeren van een directorystructuur.

Lijst 1. Voorbeeld van slechte praktijk nr. 1: Stap voor stap definitie directory boom
~ $ mkdir tmp ~ $ cd tmp ~/tmp $ mkdir a ~/tmp $ cd a ~/tmp/a $ mkdir b ~/tmp/a $ cd b ~/tmp/a/b/ $ mkdir c ~/tmp /a/b/ $ cd c ~/tmp/a/b/c $

Het is veel sneller om de optie -p mkdir te gebruiken en met één opdracht alle bovenliggende en onderliggende mappen te maken. Maar zelfs beheerders die deze optie kennen, werken nog steeds stap voor stap, waarbij ze elke submap afzonderlijk op de opdrachtregel maken. Bespaar tijd - wen er maar aan goede methoden:

Listing 2. Voorbeeld van goede werkmethode #1: Een directorystructuur definiëren met één commando
~ $ mkdir -p tmp/a/b/c

U kunt deze optie gebruiken om niet alleen een eenvoudige hiërarchie te maken, maar ook complexe mappenbomen, die erg handig zijn om in scripts te gebruiken. Bijvoorbeeld:

Lijst 3. Nog een voorbeeld van goede werkmethode nr. 1: Het definiëren van een complexe directorystructuur met één commando
~ $ mkdir -p project/(lib/ext,bin,src,doc/(html,info,pdf),demo/stat/a)

Voorheen was er slechts één reden om door een directorystructuur te stappen: de mkdir-implementatie ondersteunde deze optie niet, maar dit is op de meeste systemen niet langer relevant. IBM, AIX, mkdir, GNU mkdir en andere systemen die voldoen aan de UNIX-specificatie hebben nu deze optie.

Voor de weinige systemen die deze functie niet hebben, zou je het mkdirhier-script moeten gebruiken (zie ), dat mkdir omhult en dezelfde functie uitvoert.

~ $ mkdirhier project/(lib/ext,bin,src,doc/(html,info,pdf),demo/stat/a)

Verander paden; draag het archief niet over

Een andere slechte manier om te werken is door het archief-.tar-bestand naar een specifieke map te verplaatsen als je het archief naar die map wilt uitpakken. Dat moet je niet doen. Je kunt ze allemaal uitpakken archiefbestand.tar naar elke map - dit is waar de -C optie voor is. Gebruik de optie -C om de map op te geven die u wilt uitpakken:

Lijst 4: Voorbeeld van een goede oplossing #2: De optie -C gebruiken om een ​​.tar-archiefbestand uit te pakken
~ $ tar xvf -C tmp/a/b/c newarc.tar.gz

Het gebruik van de optie -C verdient de voorkeur boven het verplaatsen van het archiefbestand naar de gewenste map, het wijzigen van de map en het extraheren van de inhoud van het bestand - vooral als het archiefbestand zelf zich ergens anders bevindt.

Combineer uw opdrachten met controle-instructies

Je weet waarschijnlijk al dat je in de meeste shells opdrachten op dezelfde opdrachtregel kunt combineren door er een puntkomma (;) tussen te gebruiken. De puntkomma is een shell-control-operator, en hoewel het de bedoeling is om meerdere afzonderlijke opdrachten aan één enkele opdrachtregel te koppelen, is het gebruik ervan niet altijd mogelijk. Stel dat u bijvoorbeeld een puntkomma gebruikt om twee opdrachten samen te voegen, waarbij de uitvoering van de tweede opdracht volledig afhankelijk is van de succesvolle voltooiing van de eerste. Als de eerste opdracht niet werkt zoals u verwacht, wordt de tweede opdracht nog steeds uitgevoerd - en mislukt. Gebruik in plaats daarvan meer geschikte exploitant bedieningselementen (sommige worden in dit artikel beschreven). Als je schild ze ondersteunt, zullen ze even wennen zijn.

Voer een opdracht alleen uit als een andere opdracht een nulwaarde retourneert

Gebruik de && control-operator om twee opdrachten zo te combineren dat de tweede opdracht alleen wordt uitgevoerd als de eerste terugkeert nulwaarde. Met andere woorden: als het eerste commando slaagt, wordt het tweede commando ook uitgevoerd. Als het eerste commando niet wordt uitgevoerd, wordt het tweede commando helemaal niet uitgevoerd. Bijvoorbeeld:

Lijst 5. Voorbeeld van goede praktijk nr. 3: Combineer commando's met controle-instructies
~ $ cd tmp/a/b/c && tar xvf ~/archive.tar

Dit voorbeeld extraheert de inhoud van het archief in de map ~/tmp/a/b/c, als die map bestaat. Als de map niet bestaat, wordt de opdracht tar niet uitgevoerd en wordt er niets uit het archief gehaald.

Voer een opdracht alleen uit als een andere opdracht een waarde retourneert die niet nul is

Op dezelfde manier is de besturingsoperator || scheidt de twee opdrachten en voert de tweede opdracht alleen uit als de eerste opdracht een waarde anders dan nul retourneert. Met andere woorden, als het eerste commando was succesvol, zal de tweede opdracht niet worden uitgevoerd. Als het eerste commando mislukt, dan het tweede zal beginnen. Deze operator wordt vaak gebruikt om te testen of een bepaalde directory bestaat, en zo niet, dan wordt deze aangemaakt:

Lijst 6. Nog een voorbeeld van goede praktijk nr. 3: Combineer commando's met controle-instructies
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c

U kunt de in deze paragraaf beschreven controleverklaringen ook combineren. Elk van hen verwijst naar de laatste opdracht die werd uitgevoerd:

Lijst 7. Gecombineerd voorbeeld van goede praktijk nr. 3: Commando's combineren met controle-instructies
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c &&

Wees voorzichtig met het gebruik van aanhalingstekens bij het werken met variabelen

Wees altijd voorzichtig met shell-uitbreiding en namen van variabelen. Eigenlijk is dit het goed idee- plaats verwijzingen naar variabelen alleen tussen dubbele aanhalingstekens als er geen speciale redenen zijn om dit niet te doen. Op dezelfde manier moet, als een variabelenaam onmiddellijk wordt gevolgd door alfanumerieke tekst, de naam van de variabele worden ingesloten beugel(()) om het te onderscheiden van de omringende tekst. Anders interpreteert de shell de afsluitende tekst als onderdeel van de variabelenaam - en het meest waarschijnlijke resultaat is dat ook nulcode opbrengst. Lijst 8 toont voorbeelden van het gebruik van aanhalingstekens met variabelenamen en de resultaten.

Opsomming 8. Voorbeeld van goede praktijk nr. 4: Het gebruiken (en niet gebruiken) van aanhalingstekens bij het werken met variabelen
~ $ ls tmp/ a b ~ $ VAR="tmp/*" ~ $ echo $VAR tmp/a tmp/b ~ $ echo "$VAR" tmp/* ~ $ echo $VARa ~ $ echo "$VARa" ~ $ echo "$(VAR)a" tmp/*a ~ $ echo $(VAR)a tmp/a ~ $

Gebruik een escape-reeks om een ​​lange tekenreeks in te voeren

Je hebt waarschijnlijk voorbeelden gezien van code waarbij een backslash (\) een lange regel voortzet, en je weet dat de meeste shells wat je typt op volgende regels, samengevoegd met een backslash, behandelen als één lange regel. Je kunt echter wel krijgen meer voordeel van deze functie op de opdrachtregel en gebruik deze vaker. De backslash is vooral handig als uw terminal niet goed omgaat met onderbrekingen van meerdere regels of als de opdrachtregel korter is dan normaal (bijvoorbeeld als u lange weg). Backslash is ook handig om delen van de betekenis te benadrukken. lange rij, zoals in het volgende voorbeeld:

Lijst 9. Voorbeeld van goede praktijk nr. 5: Backslashes gebruiken op lange strings
~ $ cd tmp/a/b/c || \ > mkdir -p tmp/a/b/c && \ > tar xvf -C tmp/a/b/c ~/archive.tar

Als alternatief is hier een andere configuratie die ook werkt:

Lijst 10. Een alternatief voorbeeld van goede praktijk nr. 5: Backslashes gebruiken op lange strings
~ $ cd tmp/a/b/c \ > || \ > mkdir -p tmp/a/b/c \ > && \ > tar xvf -C tmp/a/b/c ~/archive.tar

Wanneer u een string in meerdere regels opsplitst, behandelt de shell deze altijd als één hele string, waarbij alle backslashes en extra spaties uit de resulterende lange string worden verwijderd.

Opmerking: Wanneer u in de meeste shells op de pijl-omhoog drukt, wordt de gehele meerregel weergegeven als een enkele lange lijn.

Combineer opdrachten in een lijst

Met de meeste shells kun je sets commando's combineren in een lijst; op deze manier kun je werk van het ene team naar het andere overbrengen of op een andere manier omleiden. U kunt dit doorgaans doen door een lijst met opdrachten uit te voeren in een alternatieve of huidige shell.

Een lijst met opdrachten uitvoeren in een extra shell

Gebruik haakjes om een ​​lijst met opdrachten in één groep te plaatsen. Hierdoor kunt u opdrachten in een extra shell uitvoeren en de uitvoer ervan omleiden of anderszins verzamelen, zoals weergegeven in het volgende voorbeeld:

Lijst 11. Voorbeeld van goede praktijk nr. 6: Een lijst met opdrachten uitvoeren in een extra shell
~ $ (cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \ > VAR=$PWD; cd ~; tar xvf -C $VAR archief.tar) \ > | mailx admin -S "Inhoud archiveren"

In dit voorbeeld wordt de inhoud van het archief uitgepakt in de map tmp/a/b/c, terwijl de uitvoer van de gegroepeerde opdrachten, inclusief een lijst met uitgepakte bestanden, naar admin wordt verzonden.

Het gebruik van extra wrappers is handig in gevallen waarin u deze overschrijft omgevingsvariabelen in de opdrachtenlijst en u wilt deze wijzigingen in uw huidige shell niet accepteren.

Voer een lijst met opdrachten uit in de huidige shell

Gebruik accolades (()) om een ​​lijst met opdrachten in te sluiten die moeten worden uitgevoerd huidig schelp. Zorg ervoor dat u spaties tussen haakjes en opdrachten toevoegt, omdat... anders interpreteert de shell de haakjes mogelijk verkeerd. Zorg er ook voor dat de laatste opdracht in de lijst wordt gevolgd door een puntkomma (;), zoals in het volgende voorbeeld:

Lijst 12. Nog een voorbeeld van goede praktijk nr. 6: Een lijst met opdrachten uitvoeren in de huidige shell
~ $ ( cp $(VAR)a . && chown -R gast.gast a && \ > tar cvf newarchive.tar a; ) | mailx admin -S "Nieuw archief"

Pas xargs toe om zoekresultaten te vinden

Gebruik de opdracht xargs als filter om te werken met de lijst met bestanden die wordt geretourneerd door te zoeken met de opdracht find. Gebruikelijk commando vinden retourneert een lijst met bestanden die aan bepaalde criteria voldoen. Deze lijst wordt doorgegeven aan xargs, die andere bewerkingen uitvoert met behulp van de lijst met bestanden als argumenten, zoals in het volgende voorbeeld:

Lijst 13. Voorbeeld van een klassiek gebruik van de opdracht xargs
~$vind | \>xargs

Denk echter niet dat xargs slechts een toevoeging is om te vinden; Dit is een van die tools waarmee je, als je er eenmaal aan gewend bent, er constant mee wilt werken, bijvoorbeeld in de volgende gevallen:

Een lijst doorgeven, gescheiden door spaties

In deze eenvoudige illustratie is xargs als een filter dat als invoer een lijst neemt (elk element op een afzonderlijke regel) en de elementen ervan op een enkele regel plaatst, gescheiden door spaties:

Lijst 14. Voorbeelduitvoer van de xargs-opdracht
~ $ xargsabc a b c ~ $

U kunt de uitvoer van elk hulpprogramma dat bestandsnamen uitvoert via xargs verzenden om een ​​lijst met argumenten op te halen voor een aantal andere hulpprogramma's die bestandsnamen als argument gebruiken, zoals in het volgende voorbeeld:

Lijst 15. Voorbeeld van het gebruik van de opdracht xargs
~/tmp $ls-1 | xargs December_Report.pdf LEESMIJ a archive.tar mkdirhier.sh ~/tmp $ ls -1 | xargs-bestand December_Report.pdf: PDF-document, versie 1.3 README: ASCII-tekst a: directory archive.tar: POSIX tar-archief mkdirhier.sh: Bourne shell-scripttekst uitvoerbaar ~/tmp $

De opdracht xargs is nuttig voor meer dan alleen het doorgeven van bestandsnamen. Gebruik het elke keer dat u tekst op één regel wilt filteren:

Lijst 16. Voorbeeld van goede praktijk nr. 7: De xargs-tool gebruiken om tekst op één regel te filteren
~/tmp $ ls -l | xargs -rw-r--r-- 7 joe joe 12043 27 januari 20:36 December_Report.pdf -rw-r--r-- 1 \ root root 238 03 december 08:19 LEESMIJ drwxr-xr-x 38 joe joe 354082 02 november \ 16:07 a -rw-r--r-- 3 joe joe 5096 14 december 14:26 archive.tar -rwxr-xr-x 1 \ joe joe 30 september 12:40 mkdirhier.sh ~/ tmp$

Wees voorzichtig bij het gebruik van xargs

Technisch gezien zijn er zeldzame gevallen waarin het gebruik van xargs problematisch kan zijn. Standaard is het teken voor het einde van het bestand het onderstrepingsteken (_); als dit teken als enige argument werd doorgegeven, wordt alles erna genegeerd. Gebruik uit voorzorg de vlag -e, die zonder argumenten het einde-van-bestand-teken uitschakelt.

Weet wanneer je grep moet gebruiken om te tellen - en wanneer je het moet vermijden

Vermijd het gebruik van wc -l na grep om het aantal ontvangen regels te tellen. Met de optie -c voor grep kunt u het aantal regels tellen dat overeenkomt met bepaalde patronen en is deze over het algemeen sneller dan de combinatie "wc after grep", zoals in het volgende voorbeeld:

Listing 17. Voorbeeld van goede werkmethode #8: Het aantal regels tellen met en zonder grep
~ $ tijd grep en tmp/a/longfile.txt | wc -l 2811 echt 0m0.097s gebruiker 0m0.006s sys 0m0.032s ~ $ tijd grep -c en tmp/a/longfile.txt 2811 echt 0m0.013s gebruiker 0m0.006s sys 0m0.005s ~ $

De -c optie is op een goede manier tellen is niet alleen te danken aan de snelheidsfactor. Wanneer je meerdere bestanden gebruikt, retourneert grep met de optie -c een aparte waarde voor elk bestand, één op elke regel, terwijl de uitvoerrichting in wc geeft totaal resultaat voor alle bestanden.

Dit voorbeeld is echter niet alleen interessant vanuit het oogpunt van prestaties; het illustreert een andere veel voorkomende fout. Deze telmethode biedt alleen aantal regels waarin overeenkomsten met het patroon zijn gevonden- en goed als dat is wat je zoekt. Maar in gevallen waarin strings meerdere overeenkomsten met een bepaald patroon kunnen hebben, zullen deze methoden geen echte waarde opleveren aantal overeenkomsten met het patroon. Gebruik wc om het aantal wedstrijden te tellen. Voer om te beginnen grep uit met de optie -o als uw versie dit ondersteunt. Deze optie wordt weergegeven alleen patroon komt overeen, één voor elke lijn, maar niet de lijn zelf. Het kan niet worden gebruikt met de optie -c, dus gebruik wc -l om het aantal regels te tellen, zoals in het volgende voorbeeld:

Voorbeeld van goede praktijk #8: Het aantal overeenkomsten met een patroon tellen met grep
~ $ grep -o en tmp/a/longfile.txt | wc -l 3402 ~ $

In dit geval is het aanroepen van wc iets sneller dan het voor de tweede keer aanroepen van grep met een dummy-patroon, zodat elke regel kan worden vergeleken en geteld (zoals grep -c).

Vergelijking van specifieke uitvoervelden, niet alleen tekenreeksen

Een tool als awk verdient de voorkeur boven grep als je alleen een patroon wilt matchen specifieke velden uitvoerregels, niet de hele regel.

Het volgende vereenvoudigde voorbeeld laat zien hoe u alleen de bestanden sorteert die in december zijn gewijzigd:

Listing 19. Voorbeeld van slechte praktijk #9: grep gebruiken om een ​​patroon in specifieke velden te vinden
~/tmp $ ls -l /tmp/a/b/c | grep Dec -rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 root root 238 Dec 03 08:19 LEESMIJ -rw-r--r- - 3 joe joe 5096 14 december 14:26 archive.tar ~/tmp $

In dit voorbeeld filtert grep de regels en drukt alle bestanden af ​​die Dec in hun naam of wijzigingsdatum hebben. Een bestand als December_Report.pdf is dus prima, zelfs als het sinds januari niet meer is gewijzigd. Dit is misschien niet wat je wilt. Om een ​​patroon in een specifiek veld te matchen, is het beter om awk te gebruiken, waarbij de relatieve operator overeenkomt met een specifiek veld, zoals weergegeven in het volgende voorbeeld

Listing 20. Voorbeeld van een goede oplossing nr. 9: awk gebruiken om een ​​patroon in specifieke velden te vinden
~/tmp $ ls -l | awk "$6 == "Dec"" -rw-r--r-- 3 joe joe 5096 14 december 14:26 archive.tar -rw-r--r-- 1 root root 238 03 december 08:19 LEESMIJ ~ /tmp$

Meer details over met behulp van awk kunt u lezen in de rubriek.

Gebruik geen kattenuitgang doorgeven

De belangrijkste en meest voorkomende fout bij het gebruik van grep is het doorgeven van de uitvoer van cat aan grep aan grep om de inhoud te doorzoeken apart bestand. Dit is een volkomen onnodige tijdverspilling omdat tools zoals grep bestandsnamen als argumenten gebruiken. Daarom is het in deze situatie absoluut niet nodig om kat te gebruiken, zoals in het volgende voorbeeld:

Listing 21. Voorbeeld van goede methode #10: grep gebruiken met en zonder cat.
~ $ tijd cat tmp/a/longfile.txt | grep en 2811 echte 0m0.015s gebruiker 0m0.003s sys 0m0.013s ~ $ tijd grep en tmp/a/longfile.txt 2811 echte 0m0.010s gebruiker 0m0.006s sys 0m0.004s ~ $

Deze fout wordt in veel gevallen gemaakt. Omdat de meeste tools ontvangen standaard invoer als argument dat een streepje (-) gebruikt, is zelfs het argument voor het gebruik van cat om talloze bestanden van stdin te diversifiëren vaak niet geldig. Eigenlijk is het noodzakelijk om eerst aaneenschakeling uit te voeren met behulp van kat met een van de verschillende filteropties.

Conclusie: Wen aan het goede

We hebben verschillende methoden bekeken om op de opdrachtregel te werken. Slechte gewoonten vertragen uw werk en leiden vaak tot onverwachte fouten. Dit artikel deelt 10 nieuwe technieken die je kunnen helpen veel van de meest voorkomende fouten weg te nemen. Raak gewend aan deze goede technieken en verbeter uw Unix-opdrachtregelvaardigheden.