Creating and Managing Files and Directories in PowerShell

Automated PowerShell workflow organizing exported reports into structured backup folders

What You’ll Learn

PowerShell can create, inspect, copy, move, rename, and remove files and directories. In this lesson, you will use these operations to prepare backup folders and organize exported system reports.

  • Create directories and files with New-Item.
  • Inspect folder contents with Get-ChildItem.
  • Copy, move, and rename items safely.
  • Remove test files and folders with care.
  • Use variables and Join-Path to build reliable paths.

The Concept

A directory, also called a folder, contains files and other directories. PowerShell represents both files and directories as items that you can manage with commands called cmdlets.

These are the most useful cmdlets for basic file system automation:

  • New-Item creates a file or directory.
  • Get-ChildItem lists the contents of a directory.
  • Copy-Item copies a file or directory while leaving the original in place.
  • Move-Item moves an item to a different location.
  • Rename-Item changes an item’s name.
  • Remove-Item deletes an item.

PowerShell paths use backslashes on Windows, such as C:\Reports. Instead of manually joining path fragments, use Join-Path. It adds the correct separator and makes scripts easier to read.

When automating backups, it is usually best to create a dedicated working folder first. That keeps practice files separate from real system files and makes it easier to clean up afterward.

Basic Example

The following example simulates an exported system health report. It creates an export folder and a backup folder, creates a report, renames it, copies it into the backup folder, and then inspects the backup.

$workspace = Join-Path (Get-Location) "SystemReportDemo"
$exportFolder = Join-Path $workspace "Exports"
$backupFolder = Join-Path $workspace "Backups"

New-Item -Path $exportFolder -ItemType Directory -Force | Out-Null
New-Item -Path $backupFolder -ItemType Directory -Force | Out-Null

$reportPath = Join-Path $exportFolder "health-check.txt"
Set-Content -Path $reportPath -Value "System health check completed."

$latestReportPath = Join-Path $exportFolder "health-check-latest.txt"
Rename-Item -Path $reportPath -NewName "health-check-latest.txt"

Copy-Item -Path $latestReportPath -Destination $backupFolder

Write-Output "Report created: $latestReportPath"
Write-Output "Report copied to: $backupFolder"

Write-Output "Backup contents:"
Get-ChildItem -Path $backupFolder -File | Select-Object -ExpandProperty Name

Expected Output

The exact beginning of each path depends on your current location. The important output is the report name and the backup listing:

Report created: ...\SystemReportDemo\Exports\health-check-latest.txt
Report copied to: ...\SystemReportDemo\Backups
Backup contents:
health-check-latest.txt

How the Code Works

A top-to-bottom PowerShell workflow starts by constructing workspace paths, creates export and backup directories, writes and renames a report, copies it to the backup folder, inspects the backup contents, and ends with optional cautious cleanup.
Build reliable paths, prepare folders, create and rename reports, copy or move them into organized locations, verify the results, and clean up only after checking the target path.

The first three variables store paths for the workspace, the export directory, and the backup directory. Get-Location returns the current directory, so the example creates its practice files beneath the location where you run the script.

New-Item -ItemType Directory creates a directory. The -Force parameter allows the command to continue when the directory already exists. This makes the script easier to run more than once.

The pipeline sends the result of New-Item to Out-Null. This hides the normal object output because the example displays its own progress messages later.

Set-Content writes text to a file. If the file does not exist, PowerShell creates it. The first file is named health-check.txt, representing an exported report.

Rename-Item changes the file name without changing its directory. The -NewName parameter receives only the new name, not the complete path.

Copy-Item places a copy of the renamed report in the backup directory. Because the destination is a directory, the copied file keeps its current name.

Finally, Get-ChildItem -File lists only files in the backup directory. The pipeline sends those file objects to Select-Object -ExpandProperty Name, which displays just their names.

Another Example

A real export process may create several reports at once. The next example creates separate report folders for daily and monthly exports, then moves files into the appropriate folder. Moving an item removes it from its original location; it does not create a second copy.

$reportWorkspace = Join-Path (Get-Location) "OrganizedReports"
$incomingFolder = Join-Path $reportWorkspace "Incoming"
$dailyFolder = Join-Path $reportWorkspace "Daily"
$monthlyFolder = Join-Path $reportWorkspace "Monthly"

New-Item -Path $incomingFolder -ItemType Directory -Force | Out-Null
New-Item -Path $dailyFolder -ItemType Directory -Force | Out-Null
New-Item -Path $monthlyFolder -ItemType Directory -Force | Out-Null

Set-Content -Path (Join-Path $incomingFolder "server-status-daily.csv") -Value "Server,Status`nSERVER01,Healthy"
Set-Content -Path (Join-Path $incomingFolder "storage-monthly.csv") -Value "Server,UsedPercent`nSERVER01,62"

Move-Item -Path (Join-Path $incomingFolder "*-daily.csv") -Destination $dailyFolder
Move-Item -Path (Join-Path $incomingFolder "*-monthly.csv") -Destination $monthlyFolder

Write-Output "Daily reports:"
Get-ChildItem -Path $dailyFolder -File | Select-Object -ExpandProperty Name

Write-Output "Monthly reports:"
Get-ChildItem -Path $monthlyFolder -File | Select-Object -ExpandProperty Name

For larger workflows, you can generate structured report data before saving it. See working with JSON data in PowerShell when your reports contain structured objects that need to be exported or transformed.

Common Mistakes

  • Using a file path as a directory path: A command such as New-Item -ItemType Directory -Path "report.txt" creates a directory named report.txt. Choose -ItemType File for files.
  • Forgetting that relative paths depend on the current directory: A path such as .\Backups is relative to the location returned by Get-Location. Use a full path or build one with Join-Path when a script needs a predictable location.
  • Confusing copy and move: Copy-Item leaves the original in place. Move-Item does not.
  • Deleting without checking the path: Remove-Item can permanently delete files. Before using it, inspect the path with Get-ChildItem or test it with Test-Path.
  • Overwriting existing content: Set-Content replaces the contents of an existing file. Use a new file name or inspect the file first when the original data matters.

For especially important cleanup commands, add -WhatIf first. For example, Remove-Item -Path $workspace -Recurse -WhatIf shows what PowerShell would remove without actually deleting it.

Try It Yourself

Create a folder named BackupPractice in your current directory. Inside it, create Exports and Backups directories. Then create a file named network-report.txt in Exports, rename it to network-report-latest.txt, and copy it to Backups.

Use Get-ChildItem to confirm that the renamed file exists in the backup directory. Do not delete the workspace until you have inspected the result.

Challenge

Build a small report-organization script with these requirements:

  • Create a workspace named ReportArchive with Incoming and Archived directories.
  • Create two sample files in Incoming: cpu-report.csv and memory-report.csv.
  • Move both files into Archived.
  • Rename cpu-report.csv to cpu-report-complete.csv after moving it.
  • Display the names of all files in Archived.

Use Join-Path for the paths and -Force when creating directories so the script can be run repeatedly.

Solution

$archiveRoot = Join-Path (Get-Location) "ReportArchive"
$incomingReports = Join-Path $archiveRoot "Incoming"
$archivedReports = Join-Path $archiveRoot "Archived"

New-Item -Path $incomingReports -ItemType Directory -Force | Out-Null
New-Item -Path $archivedReports -ItemType Directory -Force | Out-Null

$cpuReport = Join-Path $incomingReports "cpu-report.csv"
$memoryReport = Join-Path $incomingReports "memory-report.csv"

Set-Content -Path $cpuReport -Value "Server,CPUPercent`nSERVER01,48"
Set-Content -Path $memoryReport -Value "Server,MemoryPercent`nSERVER01,71"

Move-Item -Path $cpuReport -Destination $archivedReports
Move-Item -Path $memoryReport -Destination $archivedReports

$archivedCpuReport = Join-Path $archivedReports "cpu-report.csv"
Rename-Item -Path $archivedCpuReport -NewName "cpu-report-complete.csv"

Write-Output "Archived reports:"
Get-ChildItem -Path $archivedReports -File | Select-Object -ExpandProperty Name

The solution creates both directories before creating files, so each path is available when it is needed. It moves the reports from Incoming to Archived, then builds the new archived CPU path before renaming that file. The final listing should contain cpu-report-complete.csv and memory-report.csv.

Key Takeaways

  • Use New-Item to create files and directories.
  • Use Join-Path to build paths instead of manually combining strings.
  • Use Get-ChildItem to inspect files and directories.
  • Use Copy-Item for backups and Move-Item for organization.
  • Check paths carefully and use -WhatIf before potentially destructive cleanup.

Once your script works locally, you can run recurring Windows maintenance automation with PowerShell scheduled tasks.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top