跳到主要内容

文件操作

文件操作是系统管理中最常见的任务之一。PowerShell 提供了丰富的 cmdlet 用于文件和目录的管理,同时也支持 .NET 的 System.IO 类进行更底层的操作。

路径处理

PowerShell 驱动器

PowerShell 将文件系统映射为驱动器,可以通过驱动器语法访问:

Get-PSDrive
Get-PSDrive -PSProvider FileSystem

切换驱动器:

Set-Location C:
Set-Location HKLM:\SOFTWARE

路径操作 cmdlet

Split-Path:提取路径的各个部分:

$path = "C:\Users\Admin\Documents\file.txt"

Split-Path $path -Parent
Split-Path $path -Leaf
Split-Path $path -Extension
Split-Path $path -Qualifier

输出:

C:\Users\Admin\Documents
file.txt
.txt
C:

Join-Path:拼接路径:

Join-Path -Path "C:\Users" -ChildPath "Documents"
Join-Path -Path "C:\Users\Admin" -ChildPath "Documents" -AdditionalChildPath "Work", "Reports"

Resolve-Path:解析相对路径:

Resolve-Path ".\Documents"
Resolve-Path "..\Windows"

Convert-Path:转换为完整路径:

Convert-Path "~"
Convert-Path "."

Test-Path:检查路径是否存在:

Test-Path "C:\Windows"
Test-Path "C:\Temp\*.txt"
Test-Path "C:\Windows" -PathType Container

特殊路径变量

$PWD
$HOME
$env:TEMP
$env:USERPROFILE
[Environment]::GetFolderPath("MyDocuments")

目录操作

创建目录

使用 New-Item

New-Item -Path "C:\Temp\NewFolder" -ItemType Directory

使用 -Force 创建多级目录:

New-Item -Path "C:\Temp\a\b\c\d" -ItemType Directory -Force

使用 .NET 方法:

[System.IO.Directory]::CreateDirectory("C:\Temp\a\b\c")

列出目录内容

Get-ChildItem -Path "C:\Windows"
Get-ChildItem -Path "C:\" -Recurse -Depth 2
Get-ChildItem -Path "C:\Windows" -Filter "*.exe"

只列出目录:

Get-ChildItem -Directory
Get-ChildItem | Where-Object { $_.PSIsContainer }

删除目录

Remove-Item -Path "C:\Temp\OldFolder" -Recurse -Force

移动和重命名

Rename-Item -Path "C:\Temp\OldName" -NewName "NewName"
Move-Item -Path "C:\Temp\Folder" -Destination "D:\Backup\"

复制目录

Copy-Item -Path "C:\Source" -Destination "D:\Backup\Source" -Recurse

文件操作

创建文件

New-Item -Path "C:\Temp\test.txt" -ItemType File
New-Item -Path "C:\Temp\test.txt" -ItemType File -Value "Initial content"

写入文件

Set-Content:覆盖写入

Set-Content -Path "C:\Temp\test.txt" -Value "Hello World"
Set-Content -Path "C:\Temp\test.txt" -Value "Line 1", "Line 2", "Line 3"

Add-Content:追加写入

Add-Content -Path "C:\Temp\test.txt" -Value "Appended line"

Out-File:重定向输出到文件

Get-Process | Out-File -FilePath "C:\Temp\processes.txt"
Get-Process | Out-File -FilePath "C:\Temp\processes.txt" -Encoding UTF8

读取文件

Get-Content:读取全部内容

$content = Get-Content -Path "C:\Temp\test.txt"
$content[0]
$content.Count

读取部分内容:

Get-Content -Path "C:\Temp\test.txt" -TotalCount 10
Get-Content -Path "C:\Temp\test.txt" -Tail 10

逐行处理:

Get-Content -Path "C:\Temp\test.txt" | ForEach-Object {
Write-Host "处理: $_"
}

读取为单个字符串:

$content = Get-Content -Path "C:\Temp\test.txt" -Raw

复制文件

Copy-Item -Path "C:\Source\file.txt" -Destination "D:\Backup\"
Copy-Item -Path "C:\Source\*.txt" -Destination "D:\Backup\"
Copy-Item -Path "C:\Source\" -Destination "D:\Backup\" -Recurse -Filter "*.txt"

移动文件

Move-Item -Path "C:\Temp\file.txt" -Destination "D:\Archive\"

删除文件

Remove-Item -Path "C:\Temp\file.txt"
Remove-Item -Path "C:\Temp\*.tmp"
Remove-Item -Path "C:\Temp\*" -Recurse -Force

重命名文件

Rename-Item -Path "C:\Temp\old.txt" -NewName "new.txt"

文件搜索

按名称搜索

Get-ChildItem -Path "C:\" -Recurse -Filter "*.log" -ErrorAction SilentlyContinue

按内容搜索

使用 Select-String

Select-String -Path "C:\Logs\*.log" -Pattern "Error"
Select-String -Path "C:\Logs\*.log" -Pattern "Exception" -Context 2,2

搜索多个模式:

Select-String -Path "C:\Logs\*.log" -Pattern "Error", "Warning", "Exception"

使用正则表达式:

Select-String -Path "C:\Logs\*.log" -Pattern "\d{4}-\d{2}-\d{2}"

递归搜索:

Get-ChildItem -Path "C:\Logs" -Recurse -Filter "*.log" |
Select-String -Pattern "Error"

按属性搜索

按大小搜索:

Get-ChildItem -Path "C:\" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt 100MB }

按时间搜索:

$cutoff = (Get-Date).AddDays(-30)
Get-ChildItem -Path "C:\Logs" -Recurse |
Where-Object { $_.LastWriteTime -lt $cutoff }

按属性组合搜索:

Get-ChildItem -Path "C:\Logs" -Recurse |
Where-Object { $_.Extension -eq ".log" -and $_.Length -gt 1MB }

文件属性

获取文件属性

$file = Get-Item "C:\Temp\test.txt"
$file.FullName
$file.Name
$file.Extension
$file.Length
$file.CreationTime
$file.LastWriteTime
$file.LastAccessTime
$file.Attributes
$file.IsReadOnly

修改文件属性

$file = Get-Item "C:\Temp\test.txt"
$file.IsReadOnly = $true
$file.Attributes = "ReadOnly", "Hidden"

使用 Set-ItemProperty

Set-ItemProperty -Path "C:\Temp\test.txt" -Name IsReadOnly -Value $true

文件权限

获取 ACL

Get-Acl -Path "C:\Temp\test.txt"
(Get-Acl -Path "C:\Temp\test.txt").Access

设置权限

$acl = Get-Acl -Path "C:\Temp\test.txt"
$permission = "DOMAIN\User", "FullControl", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl -Path "C:\Temp\test.txt" -AclObject $acl

文件监控

FileSystemWatcher

监控文件系统变化:

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Temp"
$watcher.Filter = "*.txt"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

Register-ObjectEvent $watcher -EventName Created -Action {
Write-Host "文件创建: $($Event.SourceEventArgs.FullPath)"
}

Register-ObjectEvent $watcher -EventName Changed -Action {
Write-Host "文件修改: $($Event.SourceEventArgs.FullPath)"
}

Register-ObjectEvent $watcher -EventName Deleted -Action {
Write-Host "文件删除: $($Event.SourceEventArgs.FullPath)"
}

取消注册:

Unregister-Event -SourceIdentifier "Created"

文件压缩

创建压缩文件

PowerShell 5.1+ 提供 Compress-Archive

Compress-Archive -Path "C:\Source\*" -DestinationPath "C:\Backup\archive.zip"
Compress-Archive -Path "C:\Source\file.txt" -DestinationPath "C:\Backup\archive.zip" -Update

解压文件

Expand-Archive -Path "C:\Backup\archive.zip" -DestinationPath "C:\Extracted"

使用 .NET 压缩

Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory("C:\Source", "C:\Backup\archive.zip")
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:\Backup\archive.zip", "C:\Extracted")

实用示例

批量重命名文件

Get-ChildItem -Path "C:\Temp" -Filter "*.txt" | ForEach-Object {
$newName = $_.Name -replace "old", "new"
Rename-Item -Path $_.FullName -NewName $newName
}

清理旧文件

$cutoff = (Get-Date).AddDays(-30)
Get-ChildItem -Path "C:\Logs" -Recurse -Filter "*.log" |
Where-Object { $_.LastWriteTime -lt $cutoff } |
Remove-Item -Force

查找重复文件

$files = Get-ChildItem -Path "C:\Temp" -Recurse -File
$hashes = @{}

foreach ($file in $files) {
$hash = (Get-FileHash -Path $file.FullName -Algorithm MD5).Hash
if ($hashes.ContainsKey($hash)) {
Write-Host "重复文件: $($file.FullName)"
Write-Host "原始文件: $($hashes[$hash])"
} else {
$hashes[$hash] = $file.FullName
}
}

同步目录

$source = "C:\Source"
$destination = "D:\Backup"

Get-ChildItem -Path $source -Recurse | ForEach-Object {
$destPath = $_.FullName.Replace($source, $destination)

if ($_.PSIsContainer) {
if (!(Test-Path $destPath)) {
New-Item -Path $destPath -ItemType Directory -Force
}
} else {
$destFile = $destPath
$destDir = Split-Path $destFile -Parent

if (!(Test-Path $destDir)) {
New-Item -Path $destDir -ItemType Directory -Force
}

if (!(Test-Path $destFile) -or
(Get-Item $destFile).LastWriteTime -lt $_.LastWriteTime) {
Copy-Item -Path $_.FullName -Destination $destFile -Force
Write-Host "已复制: $($_.Name)"
}
}
}

下一步

掌握了文件操作后,接下来学习 错误处理,了解如何处理脚本中的异常和错误。