Automate the Boring Stuff with Go, Ch. 0.2: Files, Folders and Paths
Part of Automate the Boring Stuff with Go, a beginner-friendly guide to programming in Go.
Half of this book is programs that read and write files, and a quarter of all beginner trouble is a path that points at the wrong place. This chapter is the vocabulary of where things are, and one variable, PATH, that decides whether the terminal can find the programs you install.
A path is an address
A path names a file or folder by the folders you pass through to reach it. Folders are separated by / on macOS and Linux and by \ on Windows. Go accepts / on Windows too, so the book writes paths with / and they work everywhere; only when you type a path into PowerShell itself do you use \.
/Users/t/Desktop/peter-lankton/automate-the-boring-stuff-with-go/ch1/hello/main.go
Read it right to left: a file main.go, in a folder hello, in ch1, in the book’s folder, on the Desktop, in the home folder of the user t, at the root of the disk. On Windows the same idea reads C:\Users\you\....
Absolute and relative
That path above starts at the root of the disk (/, or C:\). That is an absolute path: it means the same thing wherever you are standing.
A relative path starts from the current folder. Standing in the book’s folder, ch1/hello/main.go is the same file. Standing in ch1, it is hello/main.go. The book’s commands are relative on purpose, go run ./ch1/hello, so they work on your machine, where the absolute path is different from mine. The cost is that they only work from the right folder, which is why every chapter begins “from the repository’s folder”.
Three shorthands you met in 0.1 are paths too:
.is the current folder.go run .means “run the program in this folder”../ch1/hellomeans “thech1/hellofolder, starting from here”...is the parent.../otheris a sibling folder.~is your home folder.~/go/binis the same as/Users/t/go/binfor me,/home/you/go/binon Linux, andC:\Users\you\go\binon Windows.
cd ~
pwd
/Users/t
Spaces, and other characters that bite
A space in a name splits a command into two arguments. cd My Documents tries to go into My and hands Documents to nobody. Either put the name in quotes or let Tab completion escape it for you:
cd "My Documents"
Save yourself the trouble: name your own project folders without spaces, automate-go not Automate Go. The same goes for apostrophes, brackets and most punctuation. Letters, digits, hyphens and underscores never cause trouble.
Case matters on Linux and in git, and usually does not on macOS and Windows. Main.go and main.go are two files on a Linux machine and one file on yours. Stick to lower case and the question never comes up.
Hidden files
A file or folder whose name starts with a dot is hidden from normal listings on macOS and Linux. You will create one in 0.3 (.gitignore) and git keeps its whole memory in a hidden folder (.git). Show them with ls -a (ls -Force on Windows, where hidden files are a flag on the file rather than a dot in the name):
ls -a
.
..
.CFUserTextEncoding
.DS_Store
.Trash
...
The first two entries are the current folder and its parent, listed as the names you already know.
PATH, and “command not found”
When you type go, the terminal does not search your whole disk. It looks through a short list of folders, in order, for a program called go, and runs the first one it finds. That list is the PATH, and it lives in a variable:
echo $PATH
On Windows: echo $env:PATH. The output is one long line of folders separated by : (; on Windows). Installing Go adds its folder to that list, which is why go version works after the installer and not before.
Ask which folder a command came from:
which go
/opt/homebrew/bin/go
On Windows: Get-Command go. If the answer is nothing, the program is not in any PATH folder.
Here is the trap chapter 1 warns about. Go has a second folder for programs you install with go install, and it is not on the PATH until you put it there:
go env GOPATH
/Users/t/go
The programs go into a bin folder under that, /Users/t/go/bin here. Add it to the PATH once, as chapter 1 shows for your operating system, and govulncheck, dlv, staticcheck and your own todo from chapter 16 are all found. Forget, and each of them says “command not found” the moment after you watched it install.
One more rule about PATH changes: they apply to new terminal windows. The window you edited the setting from does not know yet. When something you just installed is not found, the first fix is to close the terminal and open a new one.
Environment variables
PATH is one environment variable: a named value the terminal keeps and hands to every program it starts. HOME is another:
echo $HOME
/Users/t
On Windows the names are the same idea with a different spelling: $env:USERPROFILE is home, $env:PATH is PATH.
The book uses environment variables for anything that is a secret or a setting rather than code: chapter 17 reads SMTP_HOST and SMTP_PASS, chapter 20 reads LLM_MODEL. There are three ways to set one, and you will use all three.
For one command only. Put it in front of the command. The setting exists for that run and is gone after:
LLM_MODEL=qwen2.5:7b go run ./ch20/examples/chat-once "hello"
On Windows, PowerShell needs two statements on one line:
$env:LLM_MODEL="qwen2.5:7b"; go run ./ch20/examples/chat-once "hello"
For this terminal window. Set it once; every command until you close the window sees it:
export LLM_MODEL=qwen2.5:7b
$env:LLM_MODEL="qwen2.5:7b"
For every window from now on. Put the export line in your shell’s start-up file, ~/.zshrc on macOS or ~/.bashrc on Linux, and open a new window. On Windows, setx LLM_MODEL qwen2.5:7b stores it for future windows (not the current one), or use the Settings app: search “environment variables”.
A password belongs in the second or third form, never in a command you type, because the terminal remembers what you typed. Press the up arrow and you will see why.
Conclusion
A path is an address, absolute from the root or relative from where you stand; ., .. and ~ are addresses too; spaces need quotes; dot-files hide; PATH is the list of folders the terminal searches for programs, and it only changes for new windows; environment variables carry settings and secrets into a program without putting them in the code. That is enough to understand every “cannot find” message in the book. Next: git, in an afternoon.