Lesson 5 • Beginner
Working with Files & Folders 📁
By the end of this lesson you'll be able to list, create, copy, move, rename, read, write, and safely delete files and folders from PowerShell — the everyday skills that make the shell faster than clicking around in File Explorer.
What You'll Learn
- List folder contents with Get-ChildItem (gci / ls) and move around with Set-Location (cd)
- Create files and folders with New-Item using -ItemType
- Copy, move, and rename with Copy-Item and Move-Item
- Read and write file content with Get-Content, Set-Content, and Add-Content
- Check a path safely with Test-Path before you act on it
- Delete safely: preview with -WhatIf before using Remove-Item -Recurse
💡 Real-World Analogy
Think of PowerShell as a universal remote control for storage. A normal remote only works with one TV; PowerShell's remote works with any device that speaks the same protocol. That protocol is the provider model: the file system, the Windows Registry, environment variables and certificates are all exposed as lettered "drives" (C:, HKCU:, Env:, Cert:). Because they all share one interface, the same verbs — Get-ChildItem, Set-Location, New-Item, Remove-Item — drive every one of them. Learn the buttons once and they work everywhere.
1. The Provider Model
A provider is an adapter that makes some data store look like a disk drive, so you can browse it with file-style commands. Get-PSProvider lists the adapters; Get-PSDrive lists the drives they expose. The big payoff: once you learn the file-system cmdlets below, the exact same commands also work on the registry and environment variables — you just point them at a different drive.
# A "provider" exposes some data store as if it were a disk drive.
# Get-PSProvider lists them; Get-PSDrive lists the drives they expose.
Get-PSProvider | Select-Object Name, Drives
# Because the FileSystem and Registry are BOTH providers, the SAME
# commands work on each — you just point them at a different drive.
Set-Location C:\ # move into the C: file-system drive
Set-Location HKCU:\ # move into the registry "current user" drive (Windows)Name Drives
---- ------
Registry {HKLM, HKCU}
Alias {Alias}
Environment {Env}
FileSystem {C, D, Temp}
Function {Function}
Variable {Variable}
Certificate {Cert}HKCU: registry drive is Windows-only.2. Listing & Navigating
Get-ChildItem shows what's inside a folder — its aliases gci, ls and dir all run the same cmdlet, so use whichever feels natural. Set-Location (alias cd) moves you into a folder, and Get-Location (alias pwd) tells you where you are. Add -Recurse to dig into every sub-folder and -Filter to match a name pattern.
# Get-ChildItem lists what's inside a folder. Aliases: gci, ls, dir.
Get-ChildItem -Path C:\Projects
# Set-Location changes the current folder. Aliases: cd, sl.
Set-Location C:\Projects\my-app
Get-Location # where am I now? (alias: pwd)
# -Recurse digs into sub-folders; -Filter narrows by name pattern.
Get-ChildItem -Path C:\Projects -Recurse -Filter "*.log" Directory: C:\Projects
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2026-06-10 09:14 my-app
d---- 2026-06-11 16:02 archive
-a--- 2026-06-12 08:30 482 notes.txt
Path
----
C:\Projects\my-app
Directory: C:\Projects\my-app\logs
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2026-06-12 08:30 120 app.log3. Create, Copy, Move & Check
New-Item makes both files and folders — the -ItemType switch decides which. Copy-Item duplicates a file; Move-Item relocates it, and when the destination is just a new name in the same folder it acts as a rename (so you rarely need Rename-Item). Test-Path returns a plain True or False, which makes it perfect for an if check before you create or delete anything.
# New-Item makes files OR folders — choose with -ItemType.
New-Item -ItemType Directory -Path ".\reports" # a new folder
New-Item -ItemType File -Path ".\reports\june.txt" # an empty file
# Copy-Item duplicates; Move-Item moves OR renames (no separate Rename needed).
Copy-Item ".\reports\june.txt" ".\reports\june-backup.txt"
Move-Item ".\reports\june.txt" ".\reports\2026-june.txt" # this is a rename
# Test-Path returns a plain True/False — perfect for an "if".
Test-Path ".\reports\2026-june.txt" Directory: C:\Projects\my-app
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2026-06-15 10:01 reports
Directory: C:\Projects\my-app\reports
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2026-06-15 10:01 0 june.txt
TrueNow you try. The script below is almost complete — fill in the three blanks marked ___ using the hints in the comments, then run it and check your output against the expected lines.
# 🎯 YOUR TURN — replace each ___ then run it in PowerShell.
# 1) Create a folder called "notes" in the current directory
New-Item -ItemType ___ -Path ".\notes" # 👉 Directory or File?
# 2) Write a first line into notes\todo.txt (this also CREATES the file)
Set-Content -Path ".\notes\todo.txt" -Value ___ # 👉 some "text in quotes"
# 3) Append a second line to the same file
___ -Path ".\notes\todo.txt" -Value "Walk the dog" # 👉 which cmdlet APPENDS?
# Already wired up — reads the file back once your lines work:
Get-Content ".\notes\todo.txt"
# ✅ Expected output (if line 2 was "Buy milk"):
# Buy milk
# Walk the dogBuy milk
Walk the dog___, run it, and match the expected output.4. Reading & Writing File Content
Three cmdlets cover almost everything: Set-Content writes the file (replacing whatever was there), Add-Content appends a new line to the end, and Get-Content reads it back. One thing surprises everyone: Get-Content returns an array of lines, not a single block of text — so (Get-Content file).Count is the line count and [0] is the first line.
# Set-Content WRITES (and overwrites) the whole file.
Set-Content -Path ".\reports\log.txt" -Value "Service started"
# Add-Content APPENDS a new line to the end.
Add-Content -Path ".\reports\log.txt" -Value "Request handled"
Add-Content -Path ".\reports\log.txt" -Value "Service stopped"
# Get-Content READS the file. It returns an ARRAY: one item per line.
Get-Content -Path ".\reports\log.txt"
# So .Count is the number of lines, and [0] is the first line.
(Get-Content ".\reports\log.txt").Count # 3
(Get-Content ".\reports\log.txt")[0] # the first lineService started
Request handled
Service stopped
3
Service started5. Deleting — Safely
Remove-Item deletes files and folders. To remove a folder and its contents you must add -Recurse — and that is exactly where accidents happen, because there is no recycle bin to undo it. The safety habit: run the command first with -WhatIf, which prints every action it would take without changing a single byte on disk. When the preview looks right, run it again without -WhatIf.
# Remove-Item deletes. On a FOLDER you must add -Recurse to remove
# its contents too, otherwise PowerShell prompts you for confirmation.
# ALWAYS preview first with -WhatIf — it shows what WOULD happen,
# but changes nothing on disk.
Remove-Item ".\reports" -Recurse -WhatIf
# Happy with the preview? Run the real thing (drop -WhatIf).
Remove-Item ".\reports" -RecurseWhat if: Performing the operation "Remove Directory" on target "C:\Projects\my-app\reports".
What if: Performing the operation "Remove File" on target "C:\Projects\my-app\reports\log.txt".-WhatIf nothing is actually deleted.Your turn again. Guard the delete with Test-Path so it only runs when the folder exists, and preview it safely. Fill in the two blanks:
# 🎯 YOUR TURN — only delete the folder if it actually exists.
$folder = ".\notes"
# 1) Check whether the folder exists (returns True / False)
if (___ $folder) { # 👉 which cmdlet checks a path exists?
# 2) Preview the delete safely first — add the right switch
Remove-Item $folder -Recurse ___ # 👉 the "preview, change nothing" switch
Write-Output "Previewed delete of $folder"
} else {
Write-Output "Nothing to delete"
}
# ✅ Expected output (when .\notes exists):
# What if: Performing the operation "Remove Directory" on target "...\notes".
# Previewed delete of .\notesWhat if: Performing the operation "Remove Directory" on target "C:\Projects\my-app\notes".
Previewed delete of .\notes___, run it, and match the expected output.Common Errors (and the fix)
- Deleting a whole tree by accident:
Remove-Item .\\folder -Recursewipes everything inside with no undo. Fix: run it once with-WhatIffirst to preview, then remove the switch. - "A positional parameter cannot be found": usually a path with spaces that isn't quoted, so PowerShell splits it. Fix: quote the path —
Get-Content "C:\\My Reports\\june.txt". - Treating
Get-Contentas one string: it returns an array of lines, so string operations behave oddly. Fix: use[0]for the first line,.Countfor the line count, orGet-Content -Rawfor the whole file as one string. - "Cannot remove item ... it is being used": the file is open in another program. Fix: close the program (or stop the process) holding the file, then retry.
- New-Item creates the wrong thing: leaving off
-ItemTypeor mistyping it. Fix: be explicit —-ItemType Fileor-ItemType Directory.
Pro Tips
- 💡 Preview destructive commands with
-WhatIf; PowerShell supports it onRemove-Item,Move-Item,Copy-Itemand more. - 💡 Quote every path. It costs nothing and saves you the day a folder has a space in its name.
- 💡 Live-tail a log with
Get-Content app.log -Wait— it's PowerShell'stail -f. - 💡 Pipe into
Select-Stringto grep through files:Get-ChildItem -Recurse -Filter *.ps1 | Select-String "TODO".
📋 Quick Reference
| Task | Cmdlet (alias) | Example |
|---|---|---|
| List a folder | Get-ChildItem (ls) | Get-ChildItem C:\\Projects |
| Change folder | Set-Location (cd) | Set-Location .\\reports |
| New folder | New-Item -ItemType Directory | New-Item -ItemType Directory -Path .\\logs |
| New file | New-Item -ItemType File | New-Item -ItemType File -Path a.txt |
| Copy / Move / Rename | Copy-Item / Move-Item | Move-Item a.txt b.txt |
| Write / Append / Read | Set- / Add- / Get-Content | Add-Content log.txt "line" |
| Path exists? | Test-Path | Test-Path .\\logs |
| Delete (preview first!) | Remove-Item -Recurse -WhatIf | Remove-Item .\\logs -Recurse -WhatIf |
Frequently Asked Questions
Q: What's the difference between New-Item -ItemType File and Directory?
Both use the same cmdlet; the -ItemType switch decides what gets created. -ItemType File makes an empty file at the path, and -ItemType Directory makes a folder. Forgetting -ItemType (or getting it wrong) is the most common New-Item mistake.
Q: How do I rename a file in PowerShell?
Use Rename-Item for a pure rename in place, e.g. Rename-Item old.txt new.txt. Move-Item also renames when the destination is a new name in the same folder, so Move-Item old.txt new.txt does the same thing. Both work; Rename-Item reads more clearly.
Q: Why does Get-Content give me an array instead of one string?
Get-Content reads a text file line by line and returns an array with one element per line. That means (Get-Content file).Count is the line count and [0] is the first line. If you genuinely need the whole file as a single string, use Get-Content -Raw.
Q: Is Remove-Item -Recurse dangerous?
Yes — -Recurse deletes a folder and everything inside it, and there is no recycle bin for it. Always run the command once with -WhatIf first: it prints exactly what would be removed but changes nothing. Only when the preview looks right should you drop -WhatIf.
Q: Do I really need quotes around paths?
You need quotes whenever a path contains spaces, e.g. "C:\My Reports\june.txt". Without quotes PowerShell treats the space as a separator and reads "C:\My" as the path. Quoting every path is a safe habit even when there are no spaces.
Mini-Challenge: a Daily Log Tool
No blanks this time — just a brief and an outline to keep you on track. Build it, run it, and check the result against the comment. This is exactly the kind of small script that automates a real chore.
# 🎯 MINI-CHALLENGE: a tiny "daily log" tool
# 1. Make a folder ".\daily" (use New-Item -ItemType Directory).
# 2. Write today's date as the first line of ".\daily\entries.txt"
# (use Set-Content with (Get-Date).ToString("yyyy-MM-dd") ).
# 3. Append two log lines with Add-Content.
# 4. Print how many lines the file now has
# (hint: wrap Get-Content in parentheses, then .Count).
# 5. SAFETY: preview deleting the folder with Remove-Item ... -Recurse -WhatIf
#
# ✅ Expected (after 3 lines written): the number 3
# your code here33.🎉 Lesson Complete!
- ✅ One set of cmdlets works across every provider drive (
C:,HKCU:,Env:) - ✅
Get-ChildItemlists,Set-Locationnavigates,Get-Locationtells you where you are - ✅
New-Item -ItemTypecreates files or folders;Copy-Item/Move-Itemduplicate, move and rename - ✅
Set-Contentwrites,Add-Contentappends,Get-Contentreads (as an array of lines) - ✅
Test-Pathguards your actions;Remove-Item -Recursedeletes — always preview with-WhatIffirst - ✅ Next lesson: Automation and Task Scheduling — run your scripts on a schedule
Sign up for free to track which lessons you've completed and get learning reminders.