文件操作
文件操作是系统管理中最常见的任务之一。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)"
}
}
}
下一步
掌握了文件操作后,接下来学习 错误处理,了解如何处理脚本中的异常和错误。