Managing files and folders systematically: exploring directories with Get-ChildItem, reading and writing files with Get-Content and Set-Content, path manipulation with Test-Path and Split-Path, copy, move, and delete operations, plus strategies for reading large files with streaming.

In episode 8 you became skilled at processing objects in the pipeline. But where do those objects come from? One of the biggest sources is the filesystem — logs, configuration, data, and backups. Episode 9 covers file and folder management systematically: exploring, reading, writing, copying, moving, deleting, and working with paths.
Think of the filesystem as a giant filing cabinet. File cmdlets are your hands: Get-ChildItem to see the cabinet's contents, Get-Content to open a document, Copy-Item to duplicate, and Remove-Item to discard unused documents. Master the hands, and the entire filing operation can be automated.
Get-ChildItem displays the contents of a directory — equivalent to ls in other terminals:
Get-ChildItem /var/log
Get-ChildItem /var/log -File
Get-ChildItem /var/log -Directory-File restricts to files only, -Directory to folders only. Combine with -Recurse to go into subfolders:
Get-ChildItem /data -Recurse -File
Get-ChildItem /data -Recurse -File -Filter "*.log"-Filter leverages system built-in patterns and is usually faster for simple searches. For complex patterns using regular expressions, use -Include and -Exclude — noting that both only work fully together with -Recurse:
Get-ChildItem /data -Recurse -Include "*.log", "*.txt"
Get-ChildItem /data -Recurse -Exclude "*.tmp"Four core cmdlets for file contents:
Get-Content — reads line by line.Set-Content — writes (overwrites).Add-Content — appends to the end.Out-File — writes command output to a file.Get-Content /var/log/syslog
Get-Content /var/log/syslog -Tail 20
Set-Content /tmp/catatan.txt -Value "Baris pertama"
Add-Content /tmp/catatan.txt -Value "Baris kedua"
Get-Content /tmp/catatan.txt
Get-Process | Out-File /tmp/proses.txtGet-Content -Tail 20 takes only the last 20 lines — standard for checking logs without loading everything. Out-File writes the text representation of objects; for storing structured data that can be read back, CSV and JSON files are covered in episode 10.
Note
The difference between Set-Content and Out-File: both write text, but Set-Content is designed for strings or string arrays, while Out-File captures pipeline output with default formatting. For printing readable logs, Out-File together with formatting cmdlets like Format-Table is a perfect pair.
A path is a file's address. Four cmdlets make you skilled at managing them:
| Cmdlet | Function |
|---|---|
Test-Path | Checks whether a path exists |
Split-Path | Splits path parts (folder, name, extension) |
Join-Path | Joins a folder and name into a path |
Resolve-Path | Converts relative paths to absolute |
Test-Path /data/laporan.txt
Split-Path /data/laporan/laporan-2026.txt -Parent
Split-Path /data/laporan/laporan-2026.txt -Leaf
Join-Path /data "laporan-2026.txt"
Resolve-Path /data/laporanTest-Path is the safety gate: before reading or deleting a file, check its existence first. Split-Path -Leaf takes the file name, -Parent takes the parent folder, and Join-Path assembles paths safely without fussing over separators.
The current working location is managed with Get-Location and Set-Location:
Get-Location
Set-Location /data
Get-LocationGet-Item takes the file or folder object itself (metadata), unlike Get-ChildItem which explores contents:
Get-Item /var/log/syslog |
Select-Object Name, Length, LastWriteTime, CreationTime, AttributesGet-ItemProperty and Set-ItemProperty read and change properties — attributes like ReadOnly, or dates:
$f = Get-Item /data/laporan.txt
$f.LastWriteTime
$f.Attributes
Set-ItemProperty /data/laporan.txt -Name IsReadOnly -Value $true
Set-ItemProperty /data/laporan.txt -Name LastWriteTime -Value (Get-Date "2026-07-01")An important note: LastWriteTime and CreationTime are metadata that can be changed — useful when normalizing the dates of restored files, and also why auditors don't trust a timestamp from a single file.
The complete cmdlets for the file lifecycle:
New-Item -Path /data/arsip -ItemType Directory
New-Item -Path /data/arsip/2026 -ItemType Directory-ItemType Directory creates a folder; -ItemType File creates an empty file. Creating nested folders all at once isn't automatic — -Force creates the entire chain:
New-Item -Path /data/arsip/2026/q1 -ItemType Directory -ForceOther core operations:
Copy-Item /data/laporan.txt /backup/laporan.txt
Copy-Item /data/arsip /backup/arsip -Recurse
Move-Item /data/laporan.txt /arsip/laporan.txt
Rename-Item /data/laporan.txt laporan-2026.txt
Remove-Item /tmp/sampah.txt
Remove-Item /tmp/sampah -Recurse -ForceCopy-Item and Move-Item use -Recurse when touching folders. Remove-Item -Recurse -Force is a merciless destroyer — make sure Test-Path has checked the target, and get in the habit of running it with -WhatIf first to see what would be deleted.
Warning
Does Remove-Item go to the Recycle Bin? No — deletion is permanent. There is no undo. Before deleting any folder in a script, test with -WhatIf, consider moving it to a "trash" folder first, or combine with -Confirm for manual confirmation at dangerous points.
Get-Content loads the entire file contents into memory. For gigabyte-sized logs, that's fatal. Two strategies for handling large files:
First, read a portion with -TotalCount or -Tail:
Get-Content /var/log/besar.log -TotalCount 100
Get-Content /var/log/besar.log -Tail 50Second, stream line by line with -ReadCount — processing several lines at once without loading everything:
Get-Content /var/log/besar.log -ReadCount 1000 | ForEach-Object {
foreach ($baris in $_) {
if ($baris -match "ERROR") { $baris }
}
}-ReadCount batches the reads (here 1000 lines per batch) so memory stays under control even with a giant file. For more explicit line-by-line processing, the .NET StreamReader object gives full control with ReadLine — a topic that will resurface when discussing .NET integration.
A summary of the largest files in a folder:
$folder = "/data"
if (-not (Test-Path $folder)) {
Write-Host "Folder $folder tidak ada" -ForegroundColor Red
exit 1
}
Get-ChildItem $folder -Recurse -File |
Sort-Object Length -Descending |
Select-Object -First 5 FullName,
@{Name = "UkuranMB"; Expression = { [math]::Round($_.Length / 1MB, 2) }},
LastWriteTime |
Format-Table -AutoSizeEpisode 9 makes you skilled in the filesystem: exploring with Get-ChildItem and filters like -Filter, -Include, -Exclude; reading and writing with Get-Content, Set-Content, Add-Content, and Out-File; managing paths with Test-Path, Split-Path, Join-Path, and Resolve-Path; reading metadata via Get-Item and properties; the file lifecycle with New-Item, Copy-Item, Move-Item, Rename-Item, and Remove-Item; and streaming strategies for large files.
Key takeaways:
Test-Path before risky operations — cheap and life-saving.-Recurse is required for folders; -WhatIf is required for Remove-Item.Split-Path and Join-Path make path manipulation safe and portable.-ReadCount to keep memory under control.Raw files are now manageable — but useful data is rarely in the form of random text. In episode 10 we work with CSV & structured data: CSV, JSON, and XML, the structured formats that become the intermediary language between your scripts and the outside world. See you in episode 10!