[{"data":1,"prerenderedAt":526},["ShallowReactive",2],{"mdc--7jxdip-key":3,"mdc--m770si-key":21,"mdc-5vpvfy-key":123,"mdc-2nkj87-key":144,"mdc-st45zt-key":274,"mdc-5j7xd8-key":286,"mdc--aje5de-key":417,"mdc-irdbz4-key":497,"mdc--m1d58g-key":510},{"data":4,"body":5},{},{"type":6,"children":7},"root",[8,16],{"type":9,"tag":10,"props":11,"children":12},"element","p",{},[13],{"type":14,"value":15},"text","You can now find your way around. This lesson is about changing things — making files and folders, copying them, moving them, and deleting them.",{"type":9,"tag":10,"props":17,"children":18},{},[19],{"type":14,"value":20},"One of these operations is permanent. We'll get to that.",{"data":22,"body":23},{},{"type":6,"children":24},[25,32,44,56,67,76,94,103],{"type":9,"tag":26,"props":27,"children":29},"h2",{"id":28},"making-things",[30],{"type":14,"value":31},"Making things",{"type":9,"tag":10,"props":33,"children":34},{},[35,42],{"type":9,"tag":36,"props":37,"children":39},"code",{"className":38},[],[40],{"type":14,"value":41},"touch",{"type":14,"value":43}," creates an empty file (or, if it already exists, quietly updates its timestamp without touching the contents):",{"type":9,"tag":45,"props":46,"children":50},"pre",{"className":47,"code":49,"language":14},[48],"language-text","touch notes.txt\n",[51],{"type":9,"tag":36,"props":52,"children":54},{"__ignoreMap":53},"",[55],{"type":14,"value":49},{"type":9,"tag":10,"props":57,"children":58},{},[59,65],{"type":9,"tag":36,"props":60,"children":62},{"className":61},[],[63],{"type":14,"value":64},"mkdir",{"type":14,"value":66}," creates a directory:",{"type":9,"tag":45,"props":68,"children":71},{"className":69,"code":70,"language":14},[48],"mkdir projects\n",[72],{"type":9,"tag":36,"props":73,"children":74},{"__ignoreMap":53},[75],{"type":14,"value":70},{"type":9,"tag":10,"props":77,"children":78},{},[79,84,86,92],{"type":9,"tag":36,"props":80,"children":82},{"className":81},[],[83],{"type":14,"value":64},{"type":14,"value":85}," fails if the parent doesn't exist. ",{"type":9,"tag":36,"props":87,"children":89},{"className":88},[],[90],{"type":14,"value":91},"mkdir -p",{"type":14,"value":93}," creates the whole chain, and doesn't complain if some of it is already there:",{"type":9,"tag":45,"props":95,"children":98},{"className":96,"code":97,"language":14},[48],"mkdir -p projects/website/src\n",[99],{"type":9,"tag":36,"props":100,"children":101},{"__ignoreMap":53},[102],{"type":14,"value":97},{"type":9,"tag":10,"props":104,"children":105},{},[106,108,114,116,121],{"type":14,"value":107},"That ",{"type":9,"tag":36,"props":109,"children":111},{"className":110},[],[112],{"type":14,"value":113},"-p",{"type":14,"value":115}," is why you'll see ",{"type":9,"tag":36,"props":117,"children":119},{"className":118},[],[120],{"type":14,"value":91},{"type":14,"value":122}," in nearly every setup script ever written — it's safe to run twice, which is a property worth wanting in anything automated.",{"data":124,"body":125},{},{"type":6,"children":126},[127,132],{"type":9,"tag":128,"props":129,"children":131},"terminal-teaser",{":lines":130},"[{\"cmd\":\"mkdir -p site/css\"},{\"cmd\":\"touch site/index.html site/css/main.css\"},{\"cmd\":\"ls -R site\",\"out\":\"site:\\ncss  index.html\\n\\nsite/css:\\nmain.css\"}]",[],{"type":9,"tag":10,"props":133,"children":134},{},[135,137,142],{"type":14,"value":136},"Notice ",{"type":9,"tag":36,"props":138,"children":140},{"className":139},[],[141],{"type":14,"value":41},{"type":14,"value":143}," took two arguments and made two files. Most commands accept as many as you give them.",{"data":145,"body":146},{},{"type":6,"children":147},[148,154,173,182,187,220,229,260,269],{"type":9,"tag":26,"props":149,"children":151},{"id":150},"copying-and-moving",[152],{"type":14,"value":153},"Copying and moving",{"type":9,"tag":10,"props":155,"children":156},{},[157,163,165,171],{"type":9,"tag":36,"props":158,"children":160},{"className":159},[],[161],{"type":14,"value":162},"cp",{"type":14,"value":164}," copies, ",{"type":9,"tag":36,"props":166,"children":168},{"className":167},[],[169],{"type":14,"value":170},"mv",{"type":14,"value":172}," moves. Both take the source first and the destination second:",{"type":9,"tag":45,"props":174,"children":177},{"className":175,"code":176,"language":14},[48],"cp notes.txt notes-backup.txt\nmv notes.txt archive/\n",[178],{"type":9,"tag":36,"props":179,"children":180},{"__ignoreMap":53},[181],{"type":14,"value":176},{"type":9,"tag":10,"props":183,"children":184},{},[185],{"type":14,"value":186},"Two things trip people up:",{"type":9,"tag":10,"props":188,"children":189},{},[190,204,206,211,213,218],{"type":9,"tag":191,"props":192,"children":193},"strong",{},[194,196,202],{"type":14,"value":195},"Copying a directory needs ",{"type":9,"tag":36,"props":197,"children":199},{"className":198},[],[200],{"type":14,"value":201},"-r",{"type":14,"value":203},".",{"type":14,"value":205}," By default ",{"type":9,"tag":36,"props":207,"children":209},{"className":208},[],[210],{"type":14,"value":162},{"type":14,"value":212}," refuses to copy a folder, because copying a tree is a different and much larger operation than copying one file. ",{"type":9,"tag":36,"props":214,"children":216},{"className":215},[],[217],{"type":14,"value":201},{"type":14,"value":219}," (recursive) says \"yes, the whole thing\":",{"type":9,"tag":45,"props":221,"children":224},{"className":222,"code":223,"language":14},[48],"cp -r site/ site-backup/\n",[225],{"type":9,"tag":36,"props":226,"children":227},{"__ignoreMap":53},[228],{"type":14,"value":223},{"type":9,"tag":10,"props":230,"children":231},{},[232,242,244,250,252,258],{"type":9,"tag":191,"props":233,"children":234},{},[235,240],{"type":9,"tag":36,"props":236,"children":238},{"className":237},[],[239],{"type":14,"value":170},{"type":14,"value":241}," is also how you rename.",{"type":14,"value":243}," There is no ",{"type":9,"tag":36,"props":245,"children":247},{"className":246},[],[248],{"type":14,"value":249},"rename",{"type":14,"value":251}," command in the way you'd expect. Moving a file to a new name in the same directory ",{"type":9,"tag":253,"props":254,"children":255},"em",{},[256],{"type":14,"value":257},"is",{"type":14,"value":259}," a rename:",{"type":9,"tag":45,"props":261,"children":264},{"className":262,"code":263,"language":14},[48],"mv draft.txt final.txt\n",[265],{"type":9,"tag":36,"props":266,"children":267},{"__ignoreMap":53},[268],{"type":14,"value":263},{"type":9,"tag":10,"props":270,"children":271},{},[272],{"type":14,"value":273},"That's not a hack — it's the same operation. A file's name is just an entry in a directory, so changing the name and changing the directory are the same kind of change.",{"data":275,"body":276},{},{"type":6,"children":277},[278],{"type":9,"tag":279,"props":280,"children":285},"quiz",{":answer":281,":options":282,"explanation":283,"question":284},"1","[\"report.txt is renamed to a file called \\\"reports\\\"\",\"The command fails and report.txt is untouched\",\"A reports directory is created and the file moved into it\"]","The trailing slash is the safety net — it tells `mv` you mean a directory. Without the slash, `mv report.txt reports` would silently rename the file to `reports`, which is one of the classic ways to lose track of something. Get in the habit of the trailing slash.","You run `mv report.txt reports/`. The `reports` directory does not exist. What happens?",[],{"data":287,"body":288},{},{"type":6,"children":289},[290,296,315,324,343,355,360],{"type":9,"tag":26,"props":291,"children":293},{"id":292},"deleting-and-the-thing-nobody-warns-you-about",[294],{"type":14,"value":295},"Deleting, and the thing nobody warns you about",{"type":9,"tag":10,"props":297,"children":298},{},[299,305,307,313],{"type":9,"tag":36,"props":300,"children":302},{"className":301},[],[303],{"type":14,"value":304},"rm",{"type":14,"value":306}," removes files. ",{"type":9,"tag":36,"props":308,"children":310},{"className":309},[],[311],{"type":14,"value":312},"rm -r",{"type":14,"value":314}," removes directories and everything inside them.",{"type":9,"tag":45,"props":316,"children":319},{"className":317,"code":318,"language":14},[48],"rm notes.txt\nrm -r old-project/\n",[320],{"type":9,"tag":36,"props":321,"children":322},{"__ignoreMap":53},[323],{"type":14,"value":318},{"type":9,"tag":10,"props":325,"children":326},{},[327,329,334,336,341],{"type":14,"value":328},"Here is the part that matters: ",{"type":9,"tag":191,"props":330,"children":331},{},[332],{"type":14,"value":333},"there is no trash can.",{"type":14,"value":335}," ",{"type":9,"tag":36,"props":337,"children":339},{"className":338},[],[340],{"type":14,"value":304},{"type":14,"value":342}," does not move things aside for later recovery. It unlinks them, and the space becomes available for reuse. On a normal filesystem with no backups, a deleted file is gone.",{"type":9,"tag":10,"props":344,"children":345},{},[346,348,353],{"type":14,"value":347},"This is not a flaw. The command line assumes you meant what you said. But it means a typo in an ",{"type":9,"tag":36,"props":349,"children":351},{"className":350},[],[352],{"type":14,"value":304},{"type":14,"value":354}," command is in a different category of mistake than a typo anywhere else.",{"type":9,"tag":10,"props":356,"children":357},{},[358],{"type":14,"value":359},"Two habits that will save you:",{"type":9,"tag":361,"props":362,"children":363},"ol",{},[364,399],{"type":9,"tag":365,"props":366,"children":367},"li",{},[368,381,383,389,391,397],{"type":9,"tag":191,"props":369,"children":370},{},[371,373,379],{"type":14,"value":372},"Run ",{"type":9,"tag":36,"props":374,"children":376},{"className":375},[],[377],{"type":14,"value":378},"ls",{"type":14,"value":380}," with the same argument first.",{"type":14,"value":382}," If ",{"type":9,"tag":36,"props":384,"children":386},{"className":385},[],[387],{"type":14,"value":388},"ls old-*",{"type":14,"value":390}," lists what you expect, then ",{"type":9,"tag":36,"props":392,"children":394},{"className":393},[],[395],{"type":14,"value":396},"rm -r old-*",{"type":14,"value":398}," will delete what you expect. If it lists something surprising, you just avoided a bad afternoon.",{"type":9,"tag":365,"props":400,"children":401},{},[402,415],{"type":9,"tag":191,"props":403,"children":404},{},[405,407,413],{"type":14,"value":406},"Use ",{"type":9,"tag":36,"props":408,"children":410},{"className":409},[],[411],{"type":14,"value":412},"rm -i",{"type":14,"value":414}," when deleting with wildcards.",{"type":14,"value":416}," It asks before each file. Tedious, and worth it when the pattern is doing the choosing rather than you.",{"data":418,"body":419},{},{"type":6,"children":420},[421],{"type":9,"tag":422,"props":423,"children":425},"deep-dive",{"title":424},"About `rm -rf /` and why you'll see it in jokes",[426,437,464,473,478],{"type":9,"tag":10,"props":427,"children":428},{},[429,435],{"type":9,"tag":36,"props":430,"children":432},{"className":431},[],[433],{"type":14,"value":434},"rm -rf /",{"type":14,"value":436}," means \"recursively, forcibly, delete everything starting from the root of the filesystem.\" It is the canonical example of a catastrophic command, and it shows up constantly in developer humour.",{"type":9,"tag":10,"props":438,"children":439},{},[440,442,447,449,455,457,462],{"type":14,"value":441},"Modern ",{"type":9,"tag":36,"props":443,"children":445},{"className":444},[],[446],{"type":14,"value":304},{"type":14,"value":448}," implementations refuse this specific command unless you add ",{"type":9,"tag":36,"props":450,"children":452},{"className":451},[],[453],{"type":14,"value":454},"--no-preserve-root",{"type":14,"value":456},", so the exact joke version is defanged. What is ",{"type":9,"tag":253,"props":458,"children":459},{},[460],{"type":14,"value":461},"not",{"type":14,"value":463}," defanged is the near-miss family — a stray space or an unset variable turning a targeted delete into a total one:",{"type":9,"tag":45,"props":465,"children":468},{"className":466,"code":467,"language":14},[48],"rm -rf /home/you/projects /old      # the space before /old was a typo\nrm -rf \"$DIR\"/                      # deletes / if DIR was never set\n",[469],{"type":9,"tag":36,"props":470,"children":471},{"__ignoreMap":53},[472],{"type":14,"value":467},{"type":9,"tag":10,"props":474,"children":475},{},[476],{"type":14,"value":477},"That second one has taken down real production systems. It's the reason careful scripts check their variables before deleting anything.",{"type":9,"tag":10,"props":479,"children":480},{},[481,483,488,490,495],{"type":14,"value":482},"The lesson isn't \"be scared of ",{"type":9,"tag":36,"props":484,"children":486},{"className":485},[],[487],{"type":14,"value":304},{"type":14,"value":489},"\". It's that ",{"type":9,"tag":36,"props":491,"children":493},{"className":492},[],[494],{"type":14,"value":304},{"type":14,"value":496}," does exactly what you typed, so what you typed had better be what you meant.",{"data":498,"body":499},{},{"type":6,"children":500},[501],{"type":9,"tag":502,"props":503,"children":509},"fill-blank",{":answer":504,"explanation":505,"hint":506,"placeholder":507,"prompt":508},"[\"cp -r site site-backup\",\"cp -r site/ site-backup\",\"cp -r site/ site-backup/\",\"cp -r site site-backup/\"]","Without `-r`, cp refuses and tells you it's omitting a directory.","Copying a directory needs the recursive option.","cp ...","Copy the whole `site` directory to a new directory called `site-backup`.",[],{"data":511,"body":512},{},{"type":6,"children":513},[514,521],{"type":9,"tag":279,"props":515,"children":520},{":answer":516,":options":517,"explanation":518,"question":519},"0","[\"Run the same wildcard through `ls` first to see what it matches\",\"Run it with sudo so it definitely works\",\"Run it twice to be sure it took effect\"]","The wildcard is expanded by the shell before `rm` ever sees it, so `ls` with the same pattern shows you the exact list `rm` would receive. It's a free preview of a destructive command.","Which of these is the safest habit before running a delete with a wildcard?",[],{"type":9,"tag":10,"props":522,"children":523},{},[524],{"type":14,"value":525},"Next: actually reading what's inside these files.",1787908866326]