Free Ebook cover Windows PowerShell for Beginners: Everyday Automation and System Insights

Windows PowerShell for Beginners: Everyday Automation and System Insights

New course

10 pages

Working with Files and Folders Using PowerShell Cmdlets

Capítulo 5

Estimated reading time: 7 minutes

+ Exercise

Provider-Based File System Cmdlets: One Set of Verbs, Many Locations

PowerShell treats the file system as a provider. That means you use the same style of cmdlets (with consistent verbs like Get-, New-, Copy-, Remove-) to work with paths. In this chapter, we focus on everyday file and folder automation using these cmdlets: Get-ChildItem, Set-Location, New-Item, Copy-Item, Move-Item, Remove-Item, Rename-Item, and Test-Path.

We will follow a safety-first workflow: list what exists, check paths, then modify using -WhatIf first, and finally confirm results.

Safety-First Workflow for File Operations

1) List first with Get-ChildItem

Get-ChildItem (alias: gci, dir) lists files and folders. Start by inspecting what you’re about to change.

Get-ChildItem -Path $HOME

To list only folders:

Get-ChildItem -Path $HOME -Directory

To list only files:

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

Get-ChildItem -Path $HOME -File

2) Check paths before you touch anything with Test-Path

Test-Path returns True or False. Use it to avoid errors and to prevent creating/copying into the wrong place.

Test-Path -Path "$HOME\Desktop"

Check whether a specific file exists:

Test-Path -Path "$HOME\Desktop\notes.txt"

3) Use -WhatIf for “dry runs”

Many file-changing cmdlets support -WhatIf. It shows what would happen without making changes. Use it before Copy-Item, Move-Item, Remove-Item, and often Rename-Item.

Remove-Item -Path "$HOME\Desktop\old.log" -WhatIf

4) Confirm results after changes

After a change, re-list the target folder (or test for a specific path) to verify the outcome.

Get-ChildItem -Path "$HOME\Desktop"
Test-Path -Path "$HOME\Desktop\old.log"

Set-Location: Move Your Working Context

Set-Location (alias: cd) changes the current working folder. This makes subsequent relative paths simpler and reduces mistakes from typing long paths repeatedly.

Set-Location -Path $HOME

Navigate into a subfolder:

Set-Location -Path "$HOME\Desktop"

Tip: When you’re doing a batch of operations in one folder, Set-Location helps keep commands short and readable.

Practice Workspace: Create a Safe Sandbox Folder

For the exercises, create a dedicated practice folder so you don’t accidentally modify real documents. The examples below use a folder on your Desktop, but you can choose any location.

Create the practice folder with New-Item

New-Item creates files and folders. Use -ItemType Directory for folders.

$PracticeRoot = Join-Path $HOME 'Desktop\PS-Files-Practice'
if (-not (Test-Path -Path $PracticeRoot)) { New-Item -Path $PracticeRoot -ItemType Directory }

Confirm:

Get-ChildItem -Path (Split-Path $PracticeRoot) -Directory | Where-Object Name -eq 'PS-Files-Practice'

Exercise: Create subfolders

Create a simple structure for incoming files, processed files, and temporary files.

Set-Location -Path $PracticeRoot
New-Item -Path . -Name 'Incoming'  -ItemType Directory
New-Item -Path . -Name 'Processed' -ItemType Directory
New-Item -Path . -Name 'Temp'      -ItemType Directory

Confirm:

Get-ChildItem -Path . -Directory

Wildcard Patterns and Recursion

Wildcard patterns you’ll use constantly

Wildcards help you target groups of files without listing each one.

  • * matches any number of characters (including none). Example: *.log matches all log files.
  • ? matches exactly one character. Example: file?.txt matches file1.txt but not file10.txt.
  • [abc] matches one character from a set. Example: report[12].csv matches report1.csv and report2.csv.
  • [0-9] matches a range. Example: img[0-9].jpg.

List only certain files:

Get-ChildItem -Path .\Incoming -Filter '*.txt'

Note: -Filter is handled by the file system provider and is often faster than filtering later. Use it when you can.

Recursion: include subfolders with -Recurse

Use -Recurse to search or operate through a folder tree.

Get-ChildItem -Path . -Recurse -File

Be careful with -Recurse on delete/move operations. Always dry-run first with -WhatIf.

Copy-Item and Move-Item: Safely Moving File Sets

Exercise setup: Create sample files

Create a few placeholder files so you can practice copying and renaming. New-Item can create empty files with -ItemType File.

1..5 | ForEach-Object { New-Item -Path .\Incoming -Name ("report_{0}.txt" -f $_) -ItemType File }
1..3 | ForEach-Object { New-Item -Path .\Incoming -Name ("image_{0}.jpg" -f $_) -ItemType File }

Confirm what you created:

Get-ChildItem -Path .\Incoming

Copy a set of files (dry run first)

Copy only the text reports into Processed:

Copy-Item -Path .\Incoming\report_*.txt -Destination .\Processed -WhatIf

If the output looks correct, run it again without -WhatIf:

Copy-Item -Path .\Incoming\report_*.txt -Destination .\Processed

Confirm:

Get-ChildItem -Path .\Processed -Filter 'report_*.txt'

Move a set of files (dry run first)

Move the images into Temp:

Move-Item -Path .\Incoming\image_*.jpg -Destination .\Temp -WhatIf

Then perform the move:

Move-Item -Path .\Incoming\image_*.jpg -Destination .\Temp

Confirm both sides:

Get-ChildItem -Path .\Incoming
Get-ChildItem -Path .\Temp

Rename-Item: Renaming with Patterns (Practical Approaches)

Rename-Item renames a file or folder. For multiple items, you typically combine Get-ChildItem with a loop so you can build a new name for each file.

Exercise: Add a prefix to all processed reports

Goal: rename report_1.txt to PROCESSED_report_1.txt (and so on) inside Processed.

1) List the target files first:

Get-ChildItem -Path .\Processed -Filter 'report_*.txt'

2) Dry run the rename logic by printing the old/new names:

Get-ChildItem -Path .\Processed -Filter 'report_*.txt' | ForEach-Object { "{0} -> {1}" -f $_.Name, ("PROCESSED_{0}" -f $_.Name) }

3) Rename (use -WhatIf if available in your environment; if not, keep the dry-run step above):

Get-ChildItem -Path .\Processed -Filter 'report_*.txt' | ForEach-Object { Rename-Item -Path $_.FullName -NewName ("PROCESSED_{0}" -f $_.Name) -WhatIf }

4) Run for real (remove -WhatIf):

Get-ChildItem -Path .\Processed -Filter 'report_*.txt' | ForEach-Object { Rename-Item -Path $_.FullName -NewName ("PROCESSED_{0}" -f $_.Name) }

Confirm:

Get-ChildItem -Path .\Processed

Exercise: Change file extensions safely

Sometimes you need to rename extensions (for example, .txt to .bak) for a subset of files. Always list first and be explicit about the pattern.

Dry run by showing the new names:

Get-ChildItem -Path .\Processed -Filter 'PROCESSED_*.txt' | ForEach-Object { "{0} -> {1}" -f $_.Name, ($_.BaseName + '.bak') }

Rename:

Get-ChildItem -Path .\Processed -Filter 'PROCESSED_*.txt' | ForEach-Object { Rename-Item -Path $_.FullName -NewName ($_.BaseName + '.bak') }

Confirm:

Get-ChildItem -Path .\Processed

Remove-Item: Cleaning Up (Carefully)

Remove-Item deletes files and folders. This is where the safety-first approach matters most: list targets, use -WhatIf, then delete, then confirm.

Exercise: Create temp files, then remove only temp files

Create some temp files in Temp:

1..4 | ForEach-Object { New-Item -Path .\Temp -Name ("temp_{0}.tmp" -f $_) -ItemType File }

List only .tmp files:

Get-ChildItem -Path .\Temp -Filter '*.tmp'

Dry run deletion:

Remove-Item -Path .\Temp\*.tmp -WhatIf

Delete for real:

Remove-Item -Path .\Temp\*.tmp

Confirm:

Get-ChildItem -Path .\Temp

Removing folders (and why -Recurse matters)

To remove a folder that contains items, you typically need -Recurse. Use -WhatIf first.

Remove-Item -Path .\Temp -Recurse -WhatIf

If correct, run without -WhatIf:

Remove-Item -Path .\Temp -Recurse

Confirm the folder is gone:

Test-Path -Path .\Temp

Selecting Files by Time and Size (Everyday Maintenance Tasks)

Two common cleanup patterns are: “files older than X days” and “files larger than Y MB”. You can use LastWriteTime and Length (bytes) to target these.

Find files modified in the last 7 days

$Cutoff = (Get-Date).AddDays(-7)
Get-ChildItem -Path $PracticeRoot -Recurse -File | Where-Object { $_.LastWriteTime -ge $Cutoff }

Find files older than 30 days (candidate cleanup list)

$Cutoff = (Get-Date).AddDays(-30)
Get-ChildItem -Path $PracticeRoot -Recurse -File | Where-Object { $_.LastWriteTime -lt $Cutoff }

Find files larger than 10 MB

$MinBytes = 10MB
Get-ChildItem -Path $PracticeRoot -Recurse -File | Where-Object { $_.Length -gt $MinBytes }

Exercise: Dry-run delete of old .log files

This pattern is common in temp/log folders. First list what matches, then dry-run delete, then delete.

$Cutoff = (Get-Date).AddDays(-14)
$Targets = Get-ChildItem -Path $PracticeRoot -Recurse -File -Filter '*.log' | Where-Object { $_.LastWriteTime -lt $Cutoff }
$Targets | Select-Object FullName, LastWriteTime, Length
$Targets | ForEach-Object { Remove-Item -Path $_.FullName -WhatIf }

Putting It Together: A Repeatable “Inspect, Then Act” Checklist

GoalInspectAct (dry run)Act (real)Confirm
Copy a set of filesGet-ChildItem with -FilterCopy-Item ... -WhatIfCopy-Item ...Get-ChildItem
Move a set of filesGet-ChildItemMove-Item ... -WhatIfMove-Item ...Get-ChildItem + Test-Path
Rename many filesGet-ChildItemPrint old/new namesRename-Item in a loopGet-ChildItem
Delete temp filesGet-ChildItemRemove-Item ... -WhatIfRemove-Item ...Get-ChildItem + Test-Path

Final Exercise: Clean Up the Entire Practice Folder

When you’re done practicing, remove the entire sandbox folder. This is a good time to use -WhatIf and verify the path carefully.

1) Verify the folder exists and is the one you expect:

Test-Path -Path $PracticeRoot
Get-ChildItem -Path (Split-Path $PracticeRoot) -Directory | Where-Object Name -eq (Split-Path $PracticeRoot -Leaf)

2) Dry run removal:

Remove-Item -Path $PracticeRoot -Recurse -WhatIf

3) Remove for real:

Remove-Item -Path $PracticeRoot -Recurse

4) Confirm it’s gone:

Test-Path -Path $PracticeRoot

Now answer the exercise about the content:

When you need to delete a folder that contains files and subfolders, what is the safest recommended approach in PowerShell?

You are right! Congratulations, now go to the next page

You missed! Try again.

Folders containing items typically require -Recurse to remove. A safety-first workflow is to verify the path, use -WhatIf for a dry run, then perform the real deletion and confirm with Test-Path.

Next chapter

Processes and Services: Inspecting and Managing System Activity

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.