Learn › Linux Foundations › Text Processing
printf - a hands-on Linux lab on a real virtual machine.
Print exactly the output you describe with printf: the %s, %d, and %f placeholders, the \n and \t escapes, field width and justify with %5s and %-10s, precision with %.2f, the format-reuse rule, and the %% and invalid-conversion traps. All deterministic, all in the practice terminal.
You have printed text before with echo. Type echo hello and you get hello, plus a newline you never asked for, tucked on automatically. That is fine for a quick message. But the moment you want columns that line up, numbers padded to a fixed width, or a value rounded to two decimals, echo shrugs. It prints text. It does not format it.
This lesson is about the tool that does: printf. It prints exactly the characters you describe, in exactly the shape you describe, and it adds nothing you did not write. This is the first lesson of the Text Processing module, and printf is the right place to start. Everything you build later, tables and reports and clean output, rests on being able to say precisely what a line should look like.
The black boxes in this lesson are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. There is no file to open here. Every output printf gives is built purely from the text you type, so what you see is exactly what the command spells out, the same on every machine.
Start with the plainest useful form. printf takes a format string in quotes, then the values to drop into it. The %s inside the quotes is a placeholder that means "put a string here," and the \n at the end means "newline." Type this exact command and press Enter:
printf "Hello, %s\n" world
prompt: student@linuxcamp:~$ answer: printf "Hello, %s\n" world output: Hello, world hint: Type printf, a space, the quoted format, then the word world: printf "Hello, %s\n" world
The %s was replaced by world, and the \n printed a newline so the next prompt sits on a fresh line. Notice what did NOT happen: printf added no newline of its own. The only newline you got is the one you wrote as \n. That is the whole personality of printf: it prints what you describe and not one character more. The next steps name the pieces inside that format string.
The name printf reads as print formatted. It is one of the oldest ideas in computing. The same printf lives at the heart of the C programming language, written in the early 1970s, and the shell command you are typing deliberately copies its format syntax. Learn the format string once here and you have learned it for C, for awk, for Python's older style, and for a dozen other tools that borrowed the exact same %s, %d, %f shorthand.
That is why printf feels fussy at first: it was designed for programs, not for quick chat. The payoff is total control. When you need output that lines up to the column, printf is the tool that gets you there, and the skill transfers everywhere.
Every placeholder starts with a %. You have met %s, which means string (any text). The next one is %d, which means decimal integer (a whole number). You can put several placeholders in one format string, and printf fills them left to right from the arguments you give.
Before you run the next command, decide what you expect: three %d placeholders, three numbers to feed them, and some literal text ( + and = ) sitting between them. Now run it:
printf "%d + %d = %d\n" 2 3 5
prompt: student@linuxcamp:~$ answer: printf "%d + %d = %d\n" 2 3 5 output: 2 + 3 = 5 hint: Three %d placeholders, then the three numbers as arguments: printf "%d + %d = %d\n" 2 3 5
The first %d took 2, the second took 3, the third took 5, and the literal + and = between them printed exactly as written. That is the core mechanic: the format string is a template, and each % placeholder pulls the next argument in order. %s would have printed those same numbers as plain text; %d treats them as numbers. For whole counts either looks the same, but %d is the honest choice when the value is a number.
The backslash \ inside the format string introduces an escape: a short code for a character you cannot easily type. You have already used \n, the newline. Its partner is \t, the tab, which jumps to the next tab stop and is the quick way to space columns apart.
Run a format string with two tabs in it and watch the three words spread out:
printf "a\tb\tc\n"
prompt: student@linuxcamp:~$ answer: printf "a\tb\tc\n" output: a b c hint: Put \t between each letter and \n at the end: printf "a\tb\tc\n"
The \t between each letter printed a tab, so a, b, and c landed on tab stops instead of touching. There were no % placeholders this time and no arguments, just literal text and escapes. That is allowed: a format string with no placeholders simply prints itself, escapes and all. \n and \t are the two escapes you will use constantly; a newline to end a line, a tab to space one out.
Here is where printf leaves echo far behind, and it is the reason this command opens the module. You can tell a placeholder how WIDE it should be. Write a number between the % and the s, and printf pads the value out to that many columns.
%5s means "this string, in a field 5 columns wide, pushed to the RIGHT" (padded with spaces on the left). Add a minus sign, %-10s, and it means "10 columns wide, pushed to the LEFT" (padded on the right). That single minus sign is the difference between right-aligned and left-aligned.
Run both in one line, wrapping each field in square brackets so you can see exactly where it starts and ends:
printf "[%-10s][%5s]\n" left right
prompt: student@linuxcamp:~$ answer: printf "[%-10s][%5s]\n" left right output: [left ][right] hint: Minus means left-justify. Bracket %-10s for left, then bracket %5s: printf "[%-10s][%5s]\n" left right
Read the two bracketed fields. In the first, left is four letters filling a 10-wide field, so printf added six spaces AFTER it to reach ten columns, and the closing bracket sits at column 11. In the second, right is five letters in a 5-wide field, an exact fit, so no padding was needed and it fills the brackets edge to edge. Change right to hi and %5s would pad three spaces BEFORE it, pushing it to the right edge of its field. That is how columns in a report line up: give every value the same field width and they stack into neat columns.
Numbers with a fractional part use %f, for float (a number with a decimal point). Left alone, %f prints six decimal places, which is usually more than you want. The fix is a precision: a dot and a digit count written as %.2f, meaning "this float, rounded to 2 decimal places."
Feed printf a long decimal and ask for two places:
printf "%.2f\n" 3.14159
prompt: student@linuxcamp:~$ answer: printf "%.2f\n" 3.14159 output: 3.14 hint: Dot-two before the f means two decimal places: printf "%.2f\n" 3.14159
3.14159 came out as 3.14: printf rounded it to the two places you asked for. The .2 is the precision, and you can dial it to any digit count, %.0f for a whole number, %.4f for four places. This is the everyday tool for money, percentages, and any figure that should not spill six digits past the dot. There is also a hex placeholder, %x, which prints a number in base 16, but %s, %d, and %f with a width or precision are the forms you will reach for daily.
Here is behavior that catches everyone once. If you give printf MORE arguments than the format string has placeholders, it does not stop, and it does not complain. It goes back to the start of the format string and runs it again, until every argument is used up.
The format below has exactly one %s and one \n. Watch what printf does when you hand it three words:
printf "%s\n" a b c
prompt: student@linuxcamp:~$ answer: printf "%s\n" a b c output: a b c hint: One %s, three words. printf loops the format for each: printf "%s\n" a b c
Three lines, not one. The format "%s\n" ran once for a, again for b, and again for c, printing each on its own line. This is not a bug, it is a feature: it means one small format string can process a whole list of values. Remember it, because the first time it surprises you, it looks like printf invented output you never asked for. It did not. It just reused your template until the arguments ran out.
Two mistakes are common enough to meet head-on. The first: since % starts every placeholder, how do you print a literal percent sign? You double it. %% means "print one real %." A single % followed by something printf does not recognise is the second trap, an error.
First, print a percent the right way, with %%:
printf "100%% done\n"
prompt: student@linuxcamp:~$ answer: printf "100%% done\n" output: 100% done hint: Double the percent to print one: printf "100%% done\n"
%% collapsed to a single %, so the line read 100% done. Write just one % there and printf would try to read the next character as a placeholder type. That is the second trap. If that character is not a known type, such as z, GNU printf stops and prints:
printf: %z: invalid conversion specification
It means: you wrote %z, and z is not a placeholder printf knows (the real ones are s, d, f, x, and a few more). What to check first: look at the character right after each % in your format string. It must be a valid type like s, d, or f, or a second % if you meant a literal percent sign.
Scaffolding off. No command is printed this time. You have every piece you need.
You want to print the exact text Total: 9.50 followed by a newline. The number must come from the value 9.5 passed as an argument, and it must show two decimal places, so 9.5 has to round to 9.50. Put the literal word Total: in the format string, then a float placeholder with two-place precision, then a newline. Feed it the single argument 9.5.
prompt: student@linuxcamp:~$ answer: printf "Total: %.2f\n" 9.5 output: Total: 9.50 hint: Literal text Total: then the two-place float you learned, then the argument: printf "Total: %.2f\n" 9.5
9.5 came out as 9.50, padded to the two decimal places %.2f demanded, with the literal Total: printed exactly as you typed it. You combined a literal string, a precision float placeholder, and an escape from memory, which is the same recall the real machine will ask of you. That is the everyday shape of a printf line: some fixed words, a placeholder or two for the values, and a \n to close it.
You earned this cheat sheet. Every row is a piece of printf you just ran:
The one rule to carry away: printf prints exactly what your format string describes and nothing extra, so YOU control every newline, every column width, and every decimal. That is why it opens Text Processing: clean, aligned output is the foundation everything else is built on.
The difference from echo in one line: echo adds a newline for you and cannot format; printf adds nothing and formats everything. When output has to line up or round off, reach for printf. echo has its own lesson.
The practice terminal has shown you every core piece of printf. That is the %s, %d, and %f placeholders, the \n and \t escapes, field width and left-justify with %5s and %-10s, precision with %.2f, the format-reuse rule, and the two traps, %% for a literal percent and the invalid-conversion error. Every one of those you typed yourself.
The Text Processing module ends with one real Linux machine, the text-processing capstone mission, and that is where you format for real. A VM boots just for you, and its objectives use exactly what you practiced here alongside the module's other tools for cutting, sorting, and filtering text, each of which has its own lesson. One difference from here: the mission shows no commands. You read the objective, you recall the format string, you type it. That recall is what makes it stick.
Finish the other Text Processing lessons, then go format real output for yourself.
Practice printf in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.