Linux commando: pwd
Elke shell-sessie zet je ergens neer in het bestandssysteem, en bijna elk commando dat je uitvoert hangt af van waar dat "ergens" is. pwd is het commando dat de eenvoudigste vraag in Linux beantwoordt: waar ben ik nu? Het lijkt het saaiste hulpmiddel op het systeem, en toch schuilt achter die drie letters een kleine verrassing over hoe de kernel je positie echt bijhoudt, en waarom twee versies van pwd het oneens kunnen zijn over precies dezelfde map.
1. De basis
De taak van pwd is het tonen van je huidige werkmap: de map waar je shell op dit moment in staat. Elk relatief pad dat je typt, wordt vanaf dit punt gemeten. Wanneer je ls, cat notes.txt of ./build.sh uitvoert, begint de shell te zoeken vanuit je huidige map. pwd vertelt je precies waar dat startpunt is.
Twee ideeen maken pwd interessanter dan het op het eerste gezicht lijkt. Ten eerste is de huidige map per proces. Het is geen algemene instelling voor de hele machine; elk draaiend programma heeft zijn eigen map, stilletjes geerfd van het programma dat het startte. pwd toont degene die je shell toevallig vasthoudt. Ten tweede slaat de kernel je locatie niet op als een stukje tekst zoals /home/peter. Hij bewaart een directe verwijzing naar de map zelf. Het leesbare pad is iets dat uitgerekend moet worden, en sectie 6 laat zien waarom dat uitmaakt.
Het commando dat in drie letters "waar ben ik?" beantwoordt, en stilletjes onthult dat je locatie een levende verwijzing naar het bestandssysteem is, niet zomaar een tekst.
Dit artikel begint met het eenvoudigst mogelijke gebruik en bouwt op naar logische versus fysieke paden, het verschil tussen de shell-builtin en het losstaande programma, en de vreemde dingen die gebeuren als de map onder je voeten verdwijnt.
Naar bovenHet juiste mentale model: de kernel onthoudt in welke map je zit, niet hoe die heet.
pwdzet die positie terug om naar een naam die je kunt lezen.
2. Waar komt de naam vandaan?
De naam pwd is een afkorting van print working directory.
pwd = Print Working Directory
Zoals de meeste vroege Unix-commando's werd hij met opzet kort gemaakt. Vroege Unix werd getypt op trage teletype-terminals die elk teken op papier afdrukten, dus korte namen bespaarden zowel tijd als inkt. Daarom zijn zo veel kerncommando's twee of drie letters: ls (list), cp (copy), mv (move), cd (change directory) en pwd (print working directory).
Het woord "print" betekent hier "naar het scherm printen", wat in het teletype-tijdperk letterlijk op papier afdrukken betekende. Vandaag schrijft het gewoon een regel naar je terminal, maar de naam is nooit veranderd.
Naar boven3. Een korte geschiedenis
Het idee van een huidige werkmap was een van de vernieuwingen van het oorspronkelijke Unix bij Bell Labs in de vroege jaren zeventig. Zodra een bestandssysteem een boom van mappen werd, had je een manier nodig om "ergens te zijn" in die boom en om te vragen waar dat was. pwd is sindsdien een standaard Unix-hulpmiddel, en het is gedefinieerd door de POSIX-standaard die moderne systemen volgen.
| Tijdperk | Mijlpaal |
|---|---|
| Vroege jaren 70 | Unix introduceert het hierarchische bestandssysteem en het begrip werkmap |
| Klassiek Unix | pwd rekent het pad uit door via .. de boom omhoog te lopen |
| POSIX-tijdperk | pwd wordt gestandaardiseerd, met de opties -L (logisch) en -P (fysiek) |
| Vandaag | Linux beantwoordt de zoekvraag direct via de getcwd() system call; er bestaan zowel een shell-builtin als een coreutils-programma |
Een detail is belangrijk voor alles wat volgt. Op een typisch Linux-systeem zijn er twee versies van pwd. Je shell (Bash, Zsh en anderen) heeft pwd ingebouwd, en het GNU coreutils-pakket levert een apart programma op /bin/pwd. Ze zien er identiek uit, maar hun standaardgedrag verschilt. Sectie 6 legt uit hoe, en waarom het je kan verrassen.
4. Eenvoudige toepassingen
4.1 Het eenvoudigst mogelijke gebruik
Typ pwd met niets erachter. Het toont een regel: het volledige, absolute pad van waar je bent. In het voorbeeld hieronder is de regel die begint met $ wat je typt, en de regel eronder is wat het systeem teruggeeft.
$ pwd
/home/peter/projects/website
Het pad begint altijd vanaf de wortel / en is absoluut, dus het is nooit dubbelzinnig. Waar je die regel ook plakt, hij betekent dezelfde map.
4.2 Het eerste dat je typt op een vreemde server
Wanneer je op een onbekende machine inlogt via SSH, of wanneer een script je op een onverwachte plek heeft achtergelaten, is pwd de veilige eerste stap. Het leest alleen; het verandert niets. Samen met ls en whoami beantwoordt het de drie vragen die je meteen orienteren.
$ whoami
peter
$ pwd
/var/www/example.com
$ ls
config logs public_html
Samen zeggen ze: ik ben de gebruiker peter, ik sta in de webroot van de site, en dit is wat erin zit. Nu weet je dat het veilig is om iets te doen.
4.3 De variabele $PWD
De shell bewaart je huidige map ook in een variabele die $PWD heet. Meestal tonen echo "$PWD" en pwd hetzelfde.
$ echo "$PWD"
/home/peter/projects/website
De shell houdt ook een bijbehorende variabele bij: $OLDPWD bevat de map waar je in zat voor de laatste cd. Het is de waarde die cd - aandrijft, de "spring terug"-snelkoppeling.
$ cd /etc
$ cd /var
$ echo "$OLDPWD"
/etc
Het verschil is dat $PWD een tekst is die de shell opslaat en vertrouwt, terwijl je pwd kunt vragen om het echte bestandssysteem te controleren. Dat gat is klein, maar het is precies waar de verrassingen in sectie 7 vandaan komen.
4.4 pwd in je prompt
Je typt pwd minder vaak dan je zou verwachten, omdat de meeste shells al een verkorte vorm van de huidige map in de prompt zelf tonen. In Bash zet de speciale code \w de werkmap in je promptreeks $PS1.
$ PS1='\u@\h:\w\$ '
peter@server:~/projects/website$
Hier is \w de werkmap (met je home getoond als ~), \u de gebruiker en \h de hostnaam. Wanneer je prompt al toont waar je bent, wordt pwd het hulpmiddel waar je in scripts naar grijpt en wanneer de prompt verborgen is.
5. Gemiddelde toepassingen
5.1 pwd gebruiken in scripts
Binnen een script laat pwd je vastleggen waar je begon, zodat je later kunt terugkeren, of absolute paden kunt bouwen vanuit een relatief startpunt.
$ start="$(pwd)" # remember where we are
$ cd /tmp/build
$ # ... do some work ...
$ cd "$start" # come back to the exact spot
Door de uitvoer met $( ... ) op te vangen sla je de enkele regel die pwd toont op in een variabele. Dit is een veelgebruikt, betrouwbaar patroon, hoewel de meeste auteurs voor de map waar een script zelf in staat liever "$(dirname "$0")" gebruiken, omdat pwd laat zien waar het script vandaan werd uitgevoerd, niet waar het is opgeslagen.
5.2 Symbolische links maken "waar ben ik?" ingewikkeld
Een symbolische link (symlink) is een mapvermelding die naar een andere locatie wijst. Ze laten een map binnen een andere verschijnen, wat een echte vraag oproept: als je een symlink volgde om hier te komen, moet pwd dan het pad tonen dat je typte, of de echte map op schijf?
Beide antwoorden zijn nuttig, dus pwd ondersteunt ze allebei via twee opties: -L voor het logische pad en -P voor het fysieke pad.
$ ln -s /var/www/html site # "site" is a link to /var/www/html
$ cd site
$ pwd
/home/peter/site # the path you followed
Je staat in wat eruitziet als /home/peter/site, maar de echte bestanden staan in /var/www/html. De volgende sectie laat zien hoe je bewust om elk antwoord vraagt.
5.3 Logische paden: -L
De optie -L (kort voor logical) vertelt pwd om het pad te tonen zoals je het bereikte, symlinks en al. Het behoudt de naam die past bij hoe je navigeerde, wat meestal is wat een mens wil zien.
$ pwd -L
/home/peter/site # keeps the symlink in the path
Voor de shell-builtin is -L simpelweg de standaard: het toont de waarde van $PWD, het pad dat de shell onthouden heeft terwijl je rondliep.
5.4 Fysieke paden: -P
De optie -P (kort voor physical) doet het tegenovergestelde. Het lost elke symlink op en toont de echte locatie op schijf. Grijp ernaar wanneer je om het ware pad geeft, bijvoorbeeld voor een back-up, een rechtenwijziging, of iets dat zich niet door een link mag laten misleiden.
$ pwd -P
/var/www/html # the real directory, links resolved
Naar bovenLogisch is "het pad dat ik nam"; fysiek is "het pad dat er echt is". Meestal wil je logisch, omdat het past bij hoe je terechtkwam waar je bent. Gebruik fysiek wanneer de waarheid op schijf belangrijker is dan de route die je liep.
6. Geavanceerde toepassingen
6.1 De builtin en het programma zijn het oneens
Hier is het feit waar zelfs ervaren gebruikers over struikelen. Er zijn twee pwd-commando's, en hun standaardgedrag is tegenovergesteld. Controleer het zelf:
$ type pwd
pwd is a shell builtin
$ which pwd
/bin/pwd
Wanneer je pwd typt, krijg je de shell-builtin, waarvan de standaard logisch (-L) is. Het aparte programma op /bin/pwd, van GNU coreutils, staat standaard op fysiek (-P). Ga in een map achter een symlink staan en de twee tonen verschillende paden voor dezelfde plek:
$ cd /home/peter/site # a symlink to /var/www/html
$ pwd # the builtin: logical by default
/home/peter/site
$ /bin/pwd # the program: physical by default
/var/www/html
Geen van beide is fout; ze beantwoorden verschillende vragen. Maar als een script /bin/pwd aanroept en dezelfde uitvoer verwacht als een interactieve pwd, kan het verschil echte, lastig te vinden bugs veroorzaken. Wanneer het ertoe doet, wees expliciet en geef altijd zelf -L of -P mee in plaats van op de standaard te vertrouwen.
6.2 Hoe pwd het pad uberhaupt vindt
Herinner je het mentale model uit sectie 1: de kernel bewaart je positie als een verwijzing naar een map, niet als een tekst. Hoe zet een fysieke pwd die verwijzing dan terug om naar tekst zoals /var/www/html?
De klassieke methode is omhoog door de boom lopen. Elke map bevat een vermelding .. die naar zijn ouder wijst. Vanaf waar je bent kijkt pwd naar de ouder, vindt de naam die terugleidt naar de huidige map, onthoudt die, en herhaalt dit een niveau hoger, helemaal tot de wortel /. Die lijst met namen omgekeerd geeft het volledige pad.
current dir -- .. --> parent (find my name here: "html")
parent -- .. --> /var/www (find its name: "www")
/var/www -- .. --> /var (find its name: "var")
/var -- .. --> / (reached the root)
read the names in reverse: / + var + www + html = /var/www/html
Modern Linux maakt dit snel met een enkele system call, getcwd(), dus de shell loopt de boom nauwelijks nog met de hand af. Maar het oude idee verklaart nog steeds het gedrag, vooral de fout die je in de volgende sectie zult zien. De logische builtin slaat dit allemaal over: hij toont gewoon de tekst die hij in $PWD heeft bewaard, en daarom is hij direct en kan hij soms verouderd zijn.
Diezelfde getcwd()-aanroep is wat elke programmeertaal onder de motorkap gebruikt. Daarom ziet "print de werkmap" er bijna identiek uit, welk hulpmiddel je ook gebruikt:
char *getcwd(char *buf, size_t size); // C, the underlying call
os.getcwd() # Python
getcwd(); // PHP
Het commando pwd is eigenlijk maar een dunne schil rond deze ene kerneldienst.
6.3 $PWD en de werkelijkheid gelijk houden
Omdat het logische antwoord uit een opgeslagen tekst komt, klopt het alleen zolang de shell die tekst up-to-date houdt. De shell doet dit voor je elke keer dat je cd gebruikt. Problemen ontstaan wanneer iets de map onder je verplaatst zonder dat de shell het weet, en dat is precies het geval in de volgende sectie.
7. Wat de meeste gebruikers niet weten
7.1 pwd kan liegen nadat een map is verwijderd of hernoemd
Dit is het detail dat pwd echt interessant maakt. Je shell zit in een map, en vanuit een andere terminal verwijdert iemand die. Je staat nu in een map die geen naam meer heeft op schijf. Kijk hoe de twee versies van pwd volstrekt verschillend reageren:
$ cd /tmp/work
$ rmdir /tmp/work # removed from another terminal
$ pwd # the builtin: still trusts $PWD
/tmp/work
$ /bin/pwd # the program: tries to walk the tree, and fails
/bin/pwd: couldn't find directory entry in '..' with matching i-node
Beide antwoorden zijn op hun eigen manier "correct". De logische builtin toont de tekst die hij onthoudt, dus hij meldt vrolijk het oude pad, ook al is het verdwenen. Het fysieke programma probeert het pad opnieuw op te bouwen uit het echte bestandssysteem, maar de map die het nodig heeft staat niet meer in zijn ouder, dus dat lukt niet, en het zegt het ronduit. Dit ene voorbeeld laat beter dan welke uitleg ook zien dat de logische pwd een herinnering leest aan waar je was, terwijl de fysieke pwd controleert waar je echt bent.
Hetzelfde gebeurt als de map wordt hernoemd of verplaatst terwijl je erin zit. De builtin blijft de oude naam tonen; de fysieke versie toont het nieuwe ware pad (of faalt als de map weg is). De oplossing is altijd simpel: cd naar iets dat nog bestaat, zoals cd ~, en je $PWD is weer vers.
7.2 Er is bijna nooit een reden om het volledige pad twee keer te typen
Omdat pwd een schoon, absoluut pad toont, gaat het prima samen met kopieren en plakken en met commandosubstitutie. In plaats van een lang pad opnieuw te typen, vang het een keer op.
$ cd /very/deep/project/config/nginx
$ here="$(pwd)" # grab it once
$ tar -czf backup.tgz "$here"
Kleine gewoonte, echte tijdwinst: wanneer je op het punt staat een lang absoluut pad te typen waar je al in staat, laat pwd het voor je maken.
7.3 pwd is waar een relatief pad begint
Elk relatief pad in Linux krijgt stilletjes je huidige map ervoor geplakt. De naam config.php betekent eigenlijk "config.php binnen wat pwd ook toont". Het zo bekijken neemt veel verwarring weg: een script dat "een bestand niet kan vinden" wordt heel vaak simpelweg vanuit een andere map uitgevoerd dan je dacht. pwd als eerste debugstap uitvoeren maakt van een raadsel een voor de hand liggend antwoord.
7.4 De wortelmap is zijn eigen ouder
De boomwandeling in sectie 6.2 klimt van ouder naar ouder tot hij de wortel / bereikt. Maar wat houdt hem daar tegen? Het antwoord is een kleine, elegante truc die in het bestandssysteem is ingebouwd: de wortelmap is zijn eigen ouder. De vermelding .. binnen / wijst recht terug naar /.
$ cd /
$ pwd
/
$ cd .. # "up" from the root...
$ pwd
/ # ...still the root
Je kunt de hele dag cd .. typen bij de wortel en nergens heen gaan. Dit is precies waarom de wandeling in sectie 6.2 weet wanneer hij moet stoppen: hij blijft klimmen tot de ouder van een map zichzelf is, en die map kan alleen / zijn. Een aardig detail dat "waar eindigt het bestandssysteem?" in een antwoord van een regel verandert.
8. Best practices
- Voer
pwduit zodra je je verloren voelt. Op een vreemde server, of wanneer een commando zich raar gedraagt, bevestig waar je bent voordat je iets doet. Het is alleen-lezen en kan niets kapotmaken. - Wees expliciet over
-Len-Pwanneer het ertoe doet. Vertrouw in scripts niet op de standaard. Als je de echte locatie nodig hebt, schrijfpwd -P; als je het pad zoals genavigeerd nodig hebt, schrijfpwd -L. - Onthoud dat
pwden/bin/pwdverschillend standaardgedrag hebben. De builtin is logisch, het coreutils-programma is fysiek. Een script dat ze mengt, kan twee paden vergelijken die nooit bedoeld waren om overeen te komen. - Vang het pad op met
"$(pwd)", altijd tussen aanhalingstekens. Aanhalingstekens beschermen paden met spaties, die op echte systemen vaak voorkomen. - Als
pwdverouderd lijkt, doe gewoon opnieuwcd. Nadat een map onder je is verplaatst of verwijderd, zet een versecdnaar een echt pad$PWDweer goed. - Grijp naar de documentatie. Omdat er twee versies zijn, documenteren ze op twee plaatsen.
$ help pwd # the built-in version (Bash)
$ man pwd # the coreutils program at /bin/pwd
$ pwd --help # a quick option summary from the program
Let op dat help pwd de builtin beschrijft die je shell echt uitvoert, terwijl man pwd /bin/pwd beschrijft. Wanneer hun gedrag verschilt, lees dan degene die past bij het commando dat je aanroept.
9. Veelgemaakte fouten
9.1 Drie veelvoorkomende mythes
| Mythe | Werkelijkheid |
|---|---|
"pwd leest altijd het echte bestandssysteem." |
De standaard builtin is logisch: hij toont de opgeslagen $PWD-tekst, die verouderd kan zijn. |
"pwd en /bin/pwd zijn hetzelfde commando." |
De een is een shell-builtin (standaard logisch), de ander een coreutils-programma (standaard fysiek). |
"Het pad dat pwd toont is het echte pad op schijf." |
Door een symlink toont het de route die je nam. Gebruik pwd -P voor de ware locatie. |
9.2 Andere valkuilen om te vermijden
- Een verouderd pad vertrouwen na een verplaatsing. Als een map wordt hernoemd of verwijderd terwijl je erin zit, blijft de logische
pwdde oude naam tonen. Doecd ~om te resetten, of gebruikpwd -Pom de waarheid te zien. - Aannemen dat een symlink-pad en het echte pad uitwisselbaar zijn. Scripts die paden vergelijken, kunnen falen wanneer de ene kant logisch en de andere fysiek is. Kies een vorm met
-Lof-Pen gebruik die consequent. - Vergeten
"$(pwd)"tussen aanhalingstekens te zetten. Een pad zonder aanhalingstekens dat een spatie bevat, splitst in meerdere argumenten en breekt het commando. - Verwachten dat
pwdtoont waar een script staat. Het toont waar het script vandaan werd uitgevoerd. Voor de eigen locatie van het script gebruik je"$(dirname "$0")". pwdmetcdverwarren.pwdmeldt alleen je locatie; het verplaatst je nooit. Om van map te wisselen heb jecdnodig.
10. Samenvatting
Het commando pwd lijkt triviaal, maar het is een helder venster op hoe Linux je plek in het bestandssysteem bijhoudt.
pwdbetekent "print working directory". Het toont het absolute pad van de map waar je shell in staat.- De huidige map is per proces en wordt door de kernel opgeslagen als een verwijzing naar een map, niet als een stukje tekst.
pwdzet die verwijzing terug om naar een leesbaar pad. -L(logisch, de standaard builtin) toont het pad zoals je navigeerde, symlinks behouden.-P(fysiek) lost symlinks op naar de echte locatie.- Er zijn twee versies: de shell-builtin (standaard logisch) en
/bin/pwdvan coreutils (standaard fysiek). Hun standaardgedrag is tegenovergesteld. - Het logische antwoord komt uit de
$PWD-tekst, dus het kan verouderd zijn; het fysieke antwoord wordt opnieuw opgebouwd uit het bestandssysteem en faalt als de map is verwijderd. - Als een map onder je wordt verplaatst of verwijderd, kan
pwdeen oude naam tonen. Een versecdlost het op. - Documentatie staat op twee plaatsen:
help pwdvoor de builtin,man pwdvoor het programma.
Dit is het overzicht dat het bewaren waard is:
pwd print the current directory (logical, as navigated)
pwd -L force the logical path (keep symlinks)
pwd -P force the physical path (resolve symlinks)
/bin/pwd the coreutils program (physical by default)
echo "$PWD" the shell's stored copy of the path
here=$(pwd) capture the path into a variable
help pwd built-in manual (Bash)
man pwd manual for /bin/pwd
Kleine commando's als pwd verbergen een verrassende hoeveelheid van hoe Linux is gebouwd, van toestand per proces tot het verschil tussen een naam en een echte locatie op schijf. Als je servers zich gedragen op manieren die moeilijk te verklaren zijn, of je wilt een opzet die dag in dag uit makkelijker te beheren is, loont het vaak om goed naar deze fundamenten te kijken. Dat is precies het soort werk waar ik graag bij help.


Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.


