正确使用 PowerShell 命令行
命令行不是一组需要死记硬背的“神秘指令”,而是一种直接、精确地向计算机表达操作意图的方式。图形界面适合探索,命令行则更适合重复操作、批量处理、故障排查和自动化。
这篇文章专门讨论我日常使用的 PowerShell,兼顾 Windows PowerShell 5.1 与跨平台的 PowerShell 7。目标不是收集尽可能多的命令,而是建立一套可靠的使用方法:理解对象管道,知道自己在哪里、命令将影响什么、如何预览结果,以及出错后如何判断问题所在。
本文中的示例默认在普通用户权限下执行。涉及删除、覆盖、管理员权限和网络密钥时,应先确认目标,再执行操作。
1 理解命令行环境
1.1 终端、Shell 和命令并不是一回事
- 终端(Terminal):承载输入和输出的窗口,例如 Windows Terminal。
- Shell:解释命令的程序,例如 PowerShell、Command Prompt、Bash 和 Zsh。
- 命令:交给 Shell 执行的具体操作,例如
Get-ChildItem或git status。 - 进程(Process):命令运行后,由操作系统管理的程序实例。
同一终端里可以运行不同的 Shell,而同一个命令名在不同 Shell 中也可能有不同含义。因此,复制网上的命令前,首先要确认它是为 PowerShell、CMD 还是 Bash 编写的。
1.2 读懂命令提示符
PowerShell 常见的提示符如下:
PS C:\Users\name\Desktop\project>
其中:
PS表示当前使用 PowerShell;- 中间的路径是当前工作目录;
>后面才是准备输入命令的位置。
教程中的 PS C:\...>、$ 或 # 通常只是提示符,不属于命令本身,不要一起复制。
1.3 命令的一般结构
命令 参数 选项
例如:
Get-ChildItem -Path .\_posts -Filter *.markdown
这里:
Get-ChildItem是命令;-Path和-Filter是具名参数;.\_posts和*.markdown是参数值。
PowerShell 的命令通常采用“动词-名词”形式。可以用以下命令查看帮助:
Get-Help Get-ChildItem
Get-Help Get-ChildItem -Examples
Get-Help Get-ChildItem -Full
不确定命令是否存在时,可以先查询:
Get-Command git
Get-Command *Dns*
2 先确认自己在哪里
很多命令行事故并不是命令写错,而是在错误的目录中执行了正确的命令。
2.1 查看和切换目录
# 查看当前位置
Get-Location
# 查看当前目录内容
Get-ChildItem
# 包括隐藏文件
Get-ChildItem -Force
# 进入子目录
Set-Location .\cloudflare
# 返回上一级
Set-Location ..
pwd、ls 和 cd 在 PowerShell 中通常也可用,但它们多为别名。在交互操作中使用别名很方便;写脚本和教程时,完整的 cmdlet 名称更清楚。
2.2 相对路径与绝对路径
.表示当前目录;..表示上一级目录;.\assets\main.scss是相对路径;C:\Projects\blog\assets\main.scss是绝对路径。
可以用下面两条命令在操作前确认目标:
Test-Path -LiteralPath '.\assets\main.scss'
Resolve-Path -LiteralPath '.\assets\main.scss'
-LiteralPath 会把路径按原样处理,不把其中的 *、? 等字符解释为通配符。对移动、删除和重命名操作来说,它通常更安全。
2.3 路径中有空格时必须引用
Set-Location 'C:\Users\name\My Project'
单引号按字面值处理内容;双引号会展开变量:
$projectName = 'Viraha'
'项目是 $projectName' # 不展开变量
"项目是 $projectName" # 展开为:项目是 Viraha
3 文件和目录操作
3.1 查看与读取
# 查看文件列表
Get-ChildItem -File
# 递归查找 Markdown 文件
Get-ChildItem -Recurse -Filter *.markdown
# 读取整个文本文件
Get-Content -Raw -LiteralPath '.\README.md'
# 只查看前20行
Get-Content -LiteralPath '.\README.md' | Select-Object -First 20
若中文显示异常,明确指定编码通常有帮助:
Get-Content -Encoding utf8 -LiteralPath '.\README.md'
3.2 创建、复制和移动
# 创建目录
New-Item -ItemType Directory -Path '.\notes'
# 创建空文件
New-Item -ItemType File -Path '.\notes\draft.md'
# 复制文件
Copy-Item -LiteralPath '.\README.md' -Destination '.\notes\README-copy.md'
# 移动或重命名文件
Move-Item -LiteralPath '.\notes\draft.md' -Destination '.\notes\command-line.md'
执行覆盖操作前,可以先检查目标是否已经存在:
Test-Path -LiteralPath '.\notes\README-copy.md'
3.3 谨慎删除
先使用 -WhatIf 预览:
Remove-Item -LiteralPath '.\notes\command-line.md' -WhatIf
确认输出中的目标完全正确后,才考虑移除 -WhatIf。对递归删除尤其要谨慎:不要把工作区根目录、用户目录、未展开的变量或不确定的通配符作为删除目标。
一个稳妥的顺序是:
- 用
Resolve-Path获得绝对路径; - 用
Get-ChildItem查看目标内容; - 优先备份或移动到回收位置;
- 用
-WhatIf预览; - 最后才执行实际删除。
4 通配符、筛选与搜索
4.1 通配符
*匹配任意数量字符;?匹配单个字符;[0-9]匹配指定范围内的一个字符。
例如:
Get-ChildItem -Filter '*.md'
Get-ChildItem -Filter '2026-*.markdown'
通配符很方便,但用于删除和移动时也容易扩大范围。先把同样的表达式交给 Get-ChildItem,确认匹配结果后再操作。
4.2 搜索文件内容
PowerShell 自带 Select-String:
Get-ChildItem -Recurse -File |
Select-String -Pattern 'TURNSTILE_HOSTNAME'
Git 仓库中可以使用:
git grep -n "guestbook_api"
如果安装了 ripgrep,则可以使用更快的 rg:
rg -n "guestbook_api"
rg --files
工具不存在时,不要把“命令无法识别”误判为项目错误。先运行 Get-Command rg 检查是否安装,再选择 git grep 或 Select-String 替代。
5 管道、重定向与对象
5.1 PowerShell 管道传递的是对象
在 Bash 中,管道通常传递文本;PowerShell 管道主要传递带属性的对象。这使筛选和排序更可靠:
Get-ChildItem -File |
Where-Object { $_.Length -gt 10KB } |
Sort-Object Length -Descending |
Select-Object Name, Length
其中 $_ 表示管道中当前处理的对象。
5.2 输出重定向
# 覆盖写入
Get-Date > .\time.txt
# 追加写入
Get-Date >> .\time.txt
# 将错误流写入文件
some-command 2> .\error.log
# 合并标准错误与标准输出
some-command *> .\all.log
使用 > 会覆盖原文件。保存重要输出时,先确认目标文件,或使用 >> 追加。
5.3 多条命令与成功条件
分号只表示“依次执行”,不保证前一条成功:
git add README.md; git commit -m "docs: update README"
如果第一条失败,第二条仍可能运行。PowerShell 7 支持 &&,但 Windows PowerShell 5.1 不支持。编写兼容脚本时,可以显式检查退出码:
git diff --check
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
git status
$LASTEXITCODE 主要记录原生程序(如 git、node)的退出码;0 通常代表成功,非零值代表失败。
6 常用的系统与网络诊断
6.1 进程
# 查看进程
Get-Process
# 按名称筛选
Get-Process | Where-Object { $_.ProcessName -like '*ruby*' }
# 查看指定端口的连接
Get-NetTCPConnection -LocalPort 4000 -ErrorAction SilentlyContinue
结束进程会丢失该进程中尚未保存的工作。先确认进程 ID 和用途,再考虑使用 Stop-Process。
6.2 DNS、端口与 HTTP
# 查询域名解析
Resolve-DnsName viraha.online -Type A
# 检查443端口
Test-NetConnection viraha.online -Port 443
# 查看 HTTP 响应头
curl.exe -I --max-time 20 "https://viraha.online"
在 Windows PowerShell 中,curl 可能是 Invoke-WebRequest 的别名。明确写成 curl.exe 可以确保调用真正的 curl 程序。
排查网络问题时应分层判断:
- DNS 能否解析域名;
- TCP 端口能否连接;
- TLS/HTTPS 是否成功;
- HTTP 状态码和响应正文是什么;
- 浏览器代理、扩展或缓存是否改变了网络路径。
命令行请求成功但浏览器失败时,应重点检查系统代理、VPN、Clash 规则、安全 DNS、浏览器扩展和缓存,而不是立刻修改服务器配置。
7 环境变量、权限与密钥
7.1 环境变量
PowerShell 中通过 $env: 访问环境变量:
$env:Path
$env:Path -split ';'
只为当前终端设置临时变量:
$env:APP_ENV = 'development'
关闭终端后,这个临时值通常会消失。
7.2 普通权限优先
不要习惯性地以管理员身份打开终端。普通权限足以完成大多数开发工作,也能限制错误命令的影响范围。只有在修改系统设置、安装系统级组件等确有需要时,才提升权限。
遇到 Permission denied 时,先检查:
- 文件是否被其他程序占用;
- 当前目录是否允许写入;
- 文件是否只读;
- 命令是否试图修改
.git、系统目录或其他受保护位置; - 是否真的需要管理员权限。
7.3 不要泄露密钥
API Token、Secret Key、密码和管理令牌不应:
- 写进 Git 仓库;
- 放进前端 JavaScript;
- 截图公开;
- 直接出现在可共享的命令历史或日志中。
应使用 GitHub Actions Secrets、Cloudflare Worker Secrets 或本机安全的环境变量。例如:
npx wrangler secret put TURNSTILE_SECRET_KEY
命令中只包含密钥名称,具体值由交互式提示输入。
8 用 Git 管理修改
命令行与 Git 配合时,最重要的是分清三个状态:工作区、暂存区和提交历史。
8.1 查看状态与差异
# 查看哪些文件发生变化
git status
# 查看尚未暂存的具体变化
git diff
# 查看已经暂存、准备提交的变化
git diff --staged
# 检查空格和行尾问题
git diff --check
git diff 进入分页器后,按 q 返回 PowerShell。
8.2 一个稳妥的提交顺序
git status
git diff
git add path/to/file
git diff --staged
git commit -m "docs: 完善命令行使用指南"
git push origin main
尽量明确列出需要暂存的文件,而不是习惯性使用 git add .。这样能避免把临时文件、密钥或无关修改一起提交。
8.3 更新本地仓库
在工作区干净时,可以使用:
git pull --ff-only origin main
--ff-only 只允许快进合并,遇到分叉时会停止,让使用者先了解情况,而不是自动产生意外的合并提交。
不要在不了解后果时使用:
git reset --hard
git clean -fd
它们可能直接丢弃本地工作。若确实需要重置,先备份或提交重要内容,并精确确认影响范围。
9 PowerShell 常用命令与别名
PowerShell 为交互使用提供了许多熟悉的别名,但别名并不等于另一套 Shell 的同名程序。例如,Windows PowerShell 中的 curl 可能指向 Invoke-WebRequest,并不一定是 curl 可执行文件。
| 目的 | 推荐的完整命令 | 常见别名 |
|---|---|---|
| 查看当前位置 | Get-Location |
pwd、gl |
| 列出文件 | Get-ChildItem |
ls、dir、gci |
| 切换目录 | Set-Location path |
cd、sl |
| 读取文件 | Get-Content file |
cat、type、gc |
| 复制文件 | Copy-Item a b |
cp、copy、ci |
| 移动文件 | Move-Item a b |
mv、move、mi |
| 删除项目 | Remove-Item path |
rm、del、ri |
| 搜索文本 | Select-String pattern file |
sls |
| 查看进程 | Get-Process |
ps、gps |
| 排序对象 | Sort-Object Property |
sort |
| 筛选对象 | Where-Object condition |
where、? |
| 遍历对象 | ForEach-Object action |
% |
交互操作时使用 cd、ls 等别名没有问题;写脚本、文档和自动化工作流时,完整 cmdlet 更容易阅读,也能减少跨环境歧义。可以用 Get-Alias 和 Get-Alias ls 查询别名来源。
10 常见错误的排查方法
10.1 “不是 Git 仓库”
fatal: not a git repository
先运行:
Get-Location
Get-ChildItem -Force
确认当前目录或上级目录中是否存在 .git。不要因为这个错误就在任意目录执行 git init,否则可能制造嵌套仓库。
10.2 “无法识别为命令”
The term 'rg' is not recognized
可能原因包括:程序未安装、安装目录不在 PATH、命令名称拼错,或当前 Shell 不支持该语法。可以使用:
Get-Command rg -ErrorAction SilentlyContinue
$env:Path -split ';'
10.3 “找不到路径”
先确认当前位置和目标:
Get-Location
Test-Path -LiteralPath '.\目标路径'
Resolve-Path -LiteralPath '.\目标路径' -ErrorAction SilentlyContinue
常见原因是少进入或多进入了一层目录。
10.4 命令长时间无输出
不要立即重复执行。先判断命令是否可能正在等待:
- 网络响应;
- 密码或确认输入;
- 文件锁;
- 分页器;
- 大量数据处理。
网络命令可以设置超时:
curl.exe --max-time 20 "https://example.com"
查看 git diff 时若停在分页页面,按 q 退出。
10.5 警告与错误要分开看
警告通常不会中止命令,例如依赖弃用或换行符提示;错误通常伴随非零退出码并阻止目标完成。阅读输出时优先寻找:
error、fatal、failed;- HTTP 4xx/5xx 状态码;
exit code;- 最先出现的真正错误,而不是后续连锁错误。
11 一套可靠的命令行工作流
面对陌生任务时,我更愿意遵循下面的顺序:
- 定位:用
Get-Location确认当前位置; - 观察:用
Get-ChildItem、git status查看现状; - 查询:用
Get-Help、Get-Command确认命令行为; - 缩小范围:明确具体文件、目录、分支或服务;
- 预览:使用
git diff、-WhatIf或只读命令确认影响; - 执行一次:避免在结果未知时连续重复命令;
- 检查退出状态:观察错误信息和
$LASTEXITCODE; - 验证结果:重新运行只读检查,而不是仅凭“没有报错”判断成功;
- 记录与提交:把可复现的改动写进 Git,把密钥放进 Secret;
- 保留恢复路径:重要覆盖操作之前先备份。
一个简单的博客修改流程可以是:
Get-Location
git status
git diff
bundle exec jekyll build --strict_front_matter
git diff --check
git add _posts/目标文章.markdown
git diff --staged
git commit -m "docs: 更新文章"
git push origin main
12 动手练习
可以在一个临时练习目录中完成以下任务:
- 创建
command-line-practice目录并进入; - 创建
notes.txt; - 写入当前日期;
- 复制为
notes-backup.txt; - 列出目录中所有
.txt文件; - 搜索文件中的年份;
- 使用
-WhatIf预览删除备份文件; - 确认无误后再清理练习目录。
参考命令:
New-Item -ItemType Directory -Path '.\command-line-practice'
Set-Location '.\command-line-practice'
Get-Date | Set-Content -Encoding utf8 '.\notes.txt'
Copy-Item -LiteralPath '.\notes.txt' -Destination '.\notes-backup.txt'
Get-ChildItem -Filter '*.txt'
Select-String -Pattern '2026' -Path '.\*.txt'
Remove-Item -LiteralPath '.\notes-backup.txt' -WhatIf
练习的重点不是速度,而是每一步都能解释:当前目录是什么、命令将读取或修改哪个对象、如何确认结果,以及如何撤回。
结语
正确使用命令行,核心不是记住更多命令,而是形成稳定的判断习惯:先定位,后操作;先预览,后修改;先理解错误,再尝试修复;重要数据始终保留恢复路径。
当这些习惯成为本能后,命令行就不再是一块容易出错的黑色窗口,而会成为理解系统、复现流程和提高效率的可靠工具。
文章评论
欢迎围绕本文内容补充资料、分享经验或提出不同看法。请尽量保持友善并说明理由;评论经站长审核后公开。
✍️发表评论
邮箱和真实姓名不会公开;真实姓名完全选填。评论只会显示在当前文章下,并需要审核后公开。
💬本文评论