news 2026/9/17 16:53:35

PowerShell目录管理实战:从入门到自动化的高效命令手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PowerShell目录管理实战:从入门到自动化的高效命令手册

1. 为什么文件系统操作在PowerShell里比cmd顺手得多:先建立Provider心智

1.1 从一次十万文件目录的清理说起

有次线上服务器磁盘告警,备份目录不知不觉膨胀到了300多GB。我当时的第一个反应是用资源管理器打开目录,然后一层一层往下翻,看到底哪个子目录在疯狂吃空间。翻了不到十分钟就放弃了,目录层级太深,子目录又多,凭肉眼根本看不出谁是罪魁祸首。

后来我改用PowerShell,三行命令就把问题定位了:

$dir = 'D:\Backup' Get-ChildItem -Path $dir -Directory | ForEach-Object { $size = (Get-ChildItem -Path $_.FullName -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum [PSCustomObject]@{ Name = $_.Name SizeMB = [math]::Round($size / 1MB, 2) Updated = $_.LastWriteTime } } | Sort-Object SizeMB -Descending | Format-Table -AutoSize

输出的结果里,最大的子目录是谁、占了多少空间、最近修改时间是什么时候,一屏全看完。整个排查过程从“翻目录翻到怀疑人生”变成了“跑命令等结果”,这就是PowerShell处理文件系统和目录的核心价值:它把目录从一串路径文本变成了结构化的对象,你能像查数据库一样对文件系统做筛选、排序、分组、统计。

这篇文章适合谁?我觉得只要你在Windows上手工维护过目录结构——不管是运维、开发、数据分析还是普通办公人员——都值得看完。后面所有命令我都按可直接复制的标准来写,同时也把每个操作背后的原理讲清楚,免得你抄了脚本却不知道它在干什么。

1.2 Provider机制:路径不是字符串,而是数据源入口

PowerShell和cmd最本质的区别,在于它引入了一套Provider(提供程序)机制。在cmd里,C:\Users\Administrator就是一段路径文本,你做的所有操作本质上都是在跟字符串打交道。而在PowerShell里,路径是Provider的寻址方式,文件系统只是众多Provider中的一种。

用一条命令看当前会话加载了哪些Provider:

Get-PSDrive

输出会包含FileSystem、Registry、Environment、Function这些。这意味着你能用同一套命令去访问文件系统、注册表和环境变量:

Set-Location HKLM:\Software Get-ChildItem

上面的代码能让你像浏览目录一样浏览注册表键值,这在排错的时候特别有用。就是因为这套统一的抽象,你在文件系统上学到的Get-ChildItemSet-LocationTest-Path这些命令,换到注册表、证书存储、环境变量里照样适用。

理解这层逻辑后,你对“PowerShell操作文件系统”的理解就不会再停留在“会用几个命令”的层面,而是能真正理解为什么PowerShell官方文档总喜欢说“everything is an object”。目录、文件、注册表键,在PowerShell眼里都是对象,都有自己的属性(Name、FullName、Length、LastWriteTime),这才是它能做复杂处理的底层原因。

1.3 高频命令集一张表:日常文件操作只靠这几个Cmdlet

很多新手一上来就背几十个命令,其实没必要。日常文件系统操作,真正高频的Cmdlet用一只手就数得过来:

用途命令典型参数
查看当前目录Get-Location
切换目录Set-Location-Path,支持相对/绝对路径
暂存并跳转目录Push-Location/Pop-Location-StackName
列出目录内容Get-ChildItem-Directory-File-Recurse-Depth-Filter
获取单个项目Get-Item-Path-LiteralPath
创建目录/文件New-Item-ItemType Directory/File
复制Copy-Item-Recurse-Force
移动/重命名Move-Item/Rename-Item注意移动和重命名本质是同一个操作
删除Remove-Item-Recurse-Force-WhatIf
检查路径是否存在Test-Path-PathType Container/Leaf

给你一个实际的场景:列出D:\work下两层以内的所有子目录,但排除node_modules

Get-ChildItem -Path D:\work -Directory -Recurse -Depth 2 | Where-Object { $_.Name -ne 'node_modules' }

注意这里的-Depth参数,它是PowerShell 5.0以后才加入的,用来限制递归深度。没有它,-Recurse会一口气把整棵目录树都列出来,在大型项目里很容易卡死。我见过太多人用Get-ChildItem -Recurse然后抱怨PowerShell慢,十次里有八次是因为他们根本不需要那么深的遍历。

2. 路径处理是隐蔽重灾区:Join-Path、相对路径与-LiteralPath的实战差异

2.1 字符串拼接路径的反面教材

新手写脚本最常见的路径处理方式是这样的:

$root = 'D:\data' $child = 'logs' $path = $root + '\' + $child

这段代码看起来没什么问题,但埋着两个隐患。

第一个隐患:如果$root本身就来自某个函数返回值,它末尾可能带着反斜杠(例如D:\data\),这时候拼接出来就是D:\data\\logs,双反斜杠在Windows下大多数命令能容忍,但一旦跨平台或者传给某些对路径严格校验的程序,就会出问题。

第二个隐患:PowerShell 7已经跨平台了,在Linux或macOS上路径分隔符是/,如果你习惯用字符串拼接,代码一换平台就全崩。正确的做法是用Join-Path

$path = Join-Path -Path $root -ChildPath $child

Join-Path会自动处理分隔符和多余的斜杠,这是我在所有脚本里强制自己使用的习惯。脚本里一旦出现手工拼路径的地方,我都会停下来想想能不能改成Join-Path。这看起来是个小细节,但在目录层次深、路径变量多的脚本里,能帮你省掉大量调试时间。

还有一个相关命令Split-Path,用来从完整路径里拆出父目录:

Split-Path -Path 'D:\data\logs\app.log' -Parent # 返回 D:\data\logs Split-Path -Path 'D:\data\logs\app.log' -Leaf # 返回 app.log

写自动化脚本时,拿当前脚本所在目录、取配置文件名、定位日志输出目录,基本都靠这两个命令组合。

2.2 文件名里的方括号如何让脚本悄悄失败

这是一个能让人排查到崩溃的坑。

假设你的目录下有一个文件叫report[2024].txt,你想用Get-ChildItem把它找出来:

Get-ChildItem -Path 'D:\data\report[2024].txt'

你会发现怎么也找不到,或者找到一堆不该出现的文件。原因在于PowerShell的-Path参数默认支持通配符,而方括号[]在通配符语法里用来表示字符集,report[2024].txt被解释成“匹配report后跟一个2024中任意字符再跟.txt的文件”,自然匹配不到字面上的方括号。

解决办法是用-LiteralPath参数,它告诉PowerShell“这是一个字面路径,不要做任何通配符解析”:

Get-Item -LiteralPath 'D:\data\report[2024].txt'

同理,Copy-ItemRemove-ItemMove-Item这些命令都支持-LiteralPath。实际生产环境中,文件名带方括号很常见,尤其是一些自动生成的日志和导出文件。我建议:只要目标是明确已知的路径,一律用- LiteralPath;只有确实需要批量匹配时才用- Path。这条习惯能避免一整类低级错误。

顺带说一句,PowerShell 5.1在读取和处理包含中文字符的路径时,有时候会遇到编码问题导致乱码。如果你经常处理非英文路径,建议直接把PowerShell升级到7.x版本,默认UTF-8编码,对中文路径的兼容性好很多。

2.3 相对路径与工作目录:脚本在计划任务里挂掉的常见原因

我见过太多人写脚本时直接写.\output\result.csv,在终端里手动执行一切正常,但一放到计划任务里就报错“找不到路径”。原因很简单:PowerShell脚本执行时的当前工作目录,不等于脚本文件所在的目录

你在某个目录下打开PowerShell窗口,当前目录就是那个目录。但计划任务调用脚本时,工作目录默认是C:\Windows\System32,于是你写的所有相对路径全部失效。

正确的做法是,脚本开头先固定根目录:

$root = if ($PSScriptRoot) { $PSScriptRoot } else { (Get-Location).Path }

$PSScriptRoot是PowerShell 3.0以后自动定义的变量,表示脚本所在目录。哪怕你从任何地方调用这个脚本,它都能正确定位自己的位置。然后所有后续路径都基于这个$root去构建:

$dataDir = Join-Path $root 'data' $logDir = Join-Path $root 'logs' $outFile = Join-Path $dataDir 'result.csv'

if ($PSScriptRoot)这个判断是为了兼容某些老版本宿主(比如ISE的某些执行模式)下$PSScriptRoot为空的情况,属于防御性写法。这个习惯看起来不起眼,但在“脚本换了个地方执行就挂”这类问题上,是标准解法。

3. 批量文件操作实战:目录体积审计、日期归档与增量备份

3.1 给一个五层目录结构做体积Top榜

回到开头那个磁盘告警的场景。定位到最大的子目录后,你往往还要继续往深层挖。写一个可复用的函数会更方便,而且这个函数值得放进你的$PROFILE里,具体怎么做我在第5部分讲。

function Get-DirSize { param( [Parameter(Mandatory = $true)] [string]$Path, [int]$Depth = 3 ) Get-ChildItem -Path $Path -Directory -Depth $Depth -ErrorAction SilentlyContinue | ForEach-Object { $size = (Get-ChildItem -Path $_.FullName -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum if ($null -eq $size) { $size = 0 } [PSCustomObject]@{ Path = $_.FullName SizeMB = [math]::Round($size / 1MB, 2) Updated = $_.LastWriteTime } } | Sort-Object SizeMB -Descending }

这里有两个细节值得注意。

第一,Measure-Object -Property Length -Sum的返回值在目标目录为空或没有文件时,Sum属性可能为$null,不处理的话后面Round会直接报错。所以加了if ($null -eq $size) { $size = 0 }的防御。

第二,内层遍历用-File参数,只统计文件对象,不统计目录对象,这样Length属性才有意义。目录的Length属性是文件系统元数据的大小,不是目录内容的体积,不用-File统计出来的数字会偏差很大。

调用方式:

Get-DirSize -Path 'D:\projects' -Depth 5 | Select-Object -First 20 | Format-Table -AutoSize

这个函数在目录特别大时会比较慢,因为它对每个子目录都做了一次完整递归。但对日常排查来说,先看Top 20再逐层深入,定位效率已经远高于手工翻目录。

3.2 按日期批量归档:别再用资源管理器手工挑文件

另一个高频场景是将旧文件按日期归档。比如一个应用每天生成一个日期格式的日志目录,你想把三个月前的目录全部移动到归档盘。

$source = 'D:\logs\app' $archiveRoot = 'D:\logs\archive' $cutoff = (Get-Date).AddMonths(-3) Get-ChildItem -Path $source -Directory | Where-Object { $_.Name -match '^\d{8}$' -and $_.LastWriteTime -lt $cutoff } | ForEach-Object { $dest = Join-Path $archiveRoot $_.Name if (Test-Path -Path $dest) { $dest = Join-Path $archiveRoot ($_.Name + '_' + $_.LastWriteTime.ToString('yyyyMMdd')) } Move-Item -Path $_.FullName -Destination $dest -ErrorAction Stop Write-Host "Moved: $($_.FullName) -> $dest" }

这里$_.Name -match '^\d{8}$'是用正则筛选目录名恰好是8位数字的目录,避免误伤其他目录。归档前用Test-Path检查目标是否已存在,存在就追加时间戳,防止移动过程中因为重名中断。

另外一个我反复强调的操作习惯:任何删除操作之前,先加- WhatIf参数跑一遍预览

Get-ChildItem -Path $env:TEMP -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -WhatIf -Recurse -Force

-WhatIf不会真正删除,只会把将要删除的项目路径打印出来。跑完一遍确认清单没问题,再去掉-WhatIf执行正式删除。这个习惯帮我避免过至少三次“删错目录”事故,强烈建议你也养成。

3.3 大目录复制选robocopy的四个理由

很多人用PowerShell复制目录时直接写Copy-Item -Recurse,小目录没问题,但目录一大就露馅。

Copy-Item复制几千个小文件时表现很差:一是没有进度信息,你根本不知道它卡住了还是在跑;二是复制过程中遇到权限错误或文件占用,直接中断,而且不支持断点续传;三是跨分区复制大文件时速度明显不如专业复制工具;四是不保留NTFS ACL、硬链接等元数据。

这时应该用Windows自带的robocopy工具,它本身就是微软为高性能文件复制设计的:

robocopy 'D:\data' 'E:\backup\data' /E /MT:16 /R:1 /W:1 /LOG:'D:\logs\robocopy.log'

参数含义:

  • /E:复制所有子目录,包括空目录
  • /MT:16:使用16个线程并行复制,大目录速度提升明显
  • /R:1:文件复制失败时重试1次
  • /W:1:重试前等待1秒
  • /LOG::把日志写入文件,而不是刷屏

在PowerShell里调用robocopy有一个必须注意的坑:robocopy的退出码不是0和1那么简单,0到7都表示成功。很多人写完脚本习惯用$LASTEXITCODE -ne 0判断失败,结果robocopy明明成功复制完了,脚本却报错了。

正确判断方式:

robocopy $src $dst /E /MT:16 /R:1 /W:1 if ($LASTEXITCODE -lt 8) { Write-Host '复制成功' } else { Write-Host "复制失败,错误码: $LASTEXITCODE" }

大于等于8才是真正的错误。这个细节不写进脚本里,迟早会在自动化任务里翻车。

4. 当目录里有几十万个文件:PowerShell卡顿的根源与优化手法

4.1 Get-ChildItem -Recurse 慢在哪

有一回我要在项目目录里统计所有源码文件的行数,那个目录不算特别大,但文件数量接近40万。我第一次直接写:

$files = Get-ChildItem -Path 'D:\projects\src' -Recurse -File

这一行跑了将近两分钟,中途看起来像死机了一样。问题出在几个层面。

第一,Get-ChildItem -Recurse会枚举所有子目录,为每个文件系统对象(文件和目录)创建PSObject包装,这个包装过程很耗时。第二,把结果赋值给$files变量意味着所有对象都要驻留内存,40万个文件对象大约会占用1到2GB内存。第三,如果后面还要逐个处理,你等于是先花时间把所有对象创建出来放内存里,再花时间遍历处理,两步都慢。

Measure-Command可以量化:

Measure-Command { Get-ChildItem -Path 'D:\projects\src' -Recurse -File | Out-Null }

我实测这个命令在大目录上大概要90到120秒。而其实我们常常只需要文件列表的一部分,或者只需要逐个处理,根本不需要一次全拉进内存。

4.2 流式管道与数组累积的天壤之别

PowerShell管道的核心价值在于流式处理:前一个命令每产生一个对象,就立刻传给下一个命令处理,不会等所有对象都生成完才开始。

所以同一个统计需求,把结果先存数组再统计,和直接在管道里处理,体验完全不同:

# 不推荐:先全量收集再计算 $files = Get-ChildItem -Path 'D:\projects\src' -Recurse -File $files.Count $files | Measure-Object -Property Length -Sum # 推荐:让Measure-Object在管道里流式接收 Get-ChildItem -Path 'D:\projects\src' -Recurse -File | Measure-Object -Property Length -Sum

第一种写法在40万文件下会卡很久才开始输出,第二种写法虽然底层还是同样在枚举,但管道让处理过程尽早开始,感知上快很多。

另一个容易被忽视的参数是-Filter。在Get-ChildItem里,-Filter是文件系统驱动层面实现的过滤,速度远快于PowerShell层的Where-Object

# 快:Filter由文件系统驱动完成 Get-ChildItem -Path 'D:\projects\src' -Recurse -File -Filter '*.cs' # 慢:先枚举全部文件再在PowerShell里过滤 Get-ChildItem -Path 'D:\projects\src' -Recurse -File | Where-Object Extension -eq '.cs'

-Filter的语法比较简单,不支持复杂的正则表达式,但它带来的性能提升在大目录上是数量级的差别。能用一个*通配符解决的问题,就不要用Where-Object。需要注意的是,-Filter配合-Recurse使用时,过滤是发生在每一层目录枚举过程中的,这也是它快的原因。

4.3 .NET枚举器:懒人也能有的高性能方案

如果对性能还不满意,可以直接调用.NET的API。System.IO.Directory类提供了一个延迟枚举的方法:

$files = [System.IO.Directory]::EnumerateFiles( 'D:\projects\src', '*.*', [System.IO.SearchOption]::AllDirectories )

关键区别在于,Get-ChildItem -Recurse是一次性把目录树全部遍历完再返回结果,而EnumerateFiles返回的是一个延迟求值的IEnumerable,你在管道里每要一个文件,它才去磁盘上读取一个文件。这样内存占用大幅下降,启动速度也快得多。

用同样40万文件的目录实测,Get-ChildItem全量枚举加对象包装耗时约90秒,内存占用约1.2GB;换成.NET枚举器后,枚举加处理大约20秒,内存占用只有几十MB。在超大规模目录下,这个差距是决定性的。

不过.NET枚举器也有自己的问题:遇到权限拒绝的目录会直接抛异常,不像PowerShell的-ErrorAction SilentlyContinue那样可以优雅跳过。所以用它遍历系统目录时要自己做好try/catch防护:

try { [System.IO.Directory]::EnumerateFiles($path, '*.*', 'AllDirectories') | ForEach-Object { # 处理每个文件路径 } } catch [System.UnauthorizedAccessException] { Write-Warning "跳过无权限目录: $path" }

我的建议是分场景选择:日常脚本和中小目录用Get-ChildItem,代码可读性好,排错方便;明确知道目标目录文件量很大、而且主要是拿文件路径做下一步处理时,用.NET枚举器。

5. 把日常操作固化成脚本:执行策略、$PROFILE与计划任务调用

5.1 ExecutionPolicy到底拦了什么

你写好了PowerShell脚本,双击运行却弹出“因为在此系统上禁止运行脚本”,这就是执行策略(ExecutionPolicy)在起作用。

执行策略不是安全机制,它只是防止用户不小心运行脚本的提示机制。但对新手来说,它确实是第一道坎。用下面的命令可以查看当前策略:

Get-ExecutionPolicy -List

输出会显示各个作用域的设置。默认情况下,Windows客户端是Restricted,意味着不允许运行任何.ps1脚本。

建议设置为RemoteSigned,它允许本地创建的脚本运行,但从网络下载的脚本必须有签名或先解除标记:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

注意加上-Scope CurrentUser,这样只影响当前用户,不需要管理员权限,也不会污染系统级设置。

从网上下载的脚本如果被标记为来自网络,RemoteSigned策略依然会拦截。这时用Unblock-File命令解除限制:

Unblock-File -Path .\download-script.ps1

或者用Get-Item -Stream Zone.Identifier检查文件是否带有“来自网络”的区域标记。知道这个机制之后,你就不会每次遇到“禁止运行脚本”就去关掉整个执行策略了。

5.2 让自定义函数开机自动可用

我第3部分提到的Get-DirSize函数,不需要每次开新终端都手动定义一遍,把它写进$PROFILE文件就行。

$PROFILE是PowerShell自动加载的脚本文件,每次启动会话时执行。常见的痛点是你直接编辑它时提示“找不到路径”,因为文件根本不存在。稳妥的初始化方式:

$profileDir = Split-Path -Path $PROFILE -Parent if (-not (Test-Path -Path $profileDir)) { New-Item -ItemType Directory -Path $profileDir -Force } if (-not (Test-Path -Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force } notepad $PROFILE

在profile里写函数,随便拿一个说明:

function Get-DirSize { # 函数定义,和上面一致 } function Touch { param([string]$Path) if (Test-Path -Path $Path) { (Get-Item -Path $Path).LastWriteTime = Get-Date } else { New-Item -ItemType File -Path $Path -Force | Out-Null } }

然后重新打开PowerShell窗口,这些函数就都能直接用了。我自己每次拿到新机器,第一件事就是把profile配好,把常用函数固定下来。时间一长,这套自定义函数集就是用PowerShell效率最高的底气。

5.3 计划任务调用PowerShell脚本的避坑参数

把脚本自动化运行起来,最稳妥的方式是计划任务。最原始的创建方式是schtasks命令:

schtasks /Create /TN "CleanTemp" /TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File D:\scripts\cleanup.ps1" /SC DAILY /ST 03:00 /F

如果你习惯在PowerShell里直接创建:

$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File D:\scripts\cleanup.ps1' $trigger = New-ScheduledTaskTrigger -Daily -At '03:00' Register-ScheduledTask -TaskName 'DailyCleanup' -Action $action -Trigger $trigger -Description 'Daily temp cleanup' -Force

这里有几个参数值得多说一句。

-NoProfile的作用是禁止加载$PROFILE,因为计划任务环境里如果profile里有弹窗或慢操作,会拖累脚本执行。-ExecutionPolicy Bypass是为了让脚本不受执行策略阻挡,因为计划任务里的PowerShell进程和交互终端的环境不完全一样。-WindowStyle Hidden是为了不让任务跑起来时弹个黑色窗口。

但要注意,计划任务默认的工作目录是C:\Windows\System32,所以脚本内部所有路径都必须用绝对路径,或者像第2部分那样用$PSScriptRoot定位脚本所在目录。另外,计划任务跑脚本时你看不到控制台输出,所有调试信息和错误都要写到日志文件里。我常用的方法是在脚本开头加一个简化的日志函数:

$logFile = Join-Path $PSScriptRoot 'cleanup.log' function Write-Log { param([string]$Message) $line = "{0} [INFO] {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Message Add-Content -Path $logFile -Value $line } try { # 主要逻辑 Write-Log 'Cleanup started' } catch { $line = "{0} [ERROR] {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $_.Exception.Message Add-Content -Path $logFile -Value $line throw }

这套组合拳打下来,定时清理、定时备份、定时生成报告这类需求就都能可靠落地了。

最后再说一个我实际用下来的体会。PowerShell处理文件系统和目录,强在“先梳理再做”:不要一上来就想写一个上百行的脚本来解决所有问题,先用交互式命令把目录结构和数据摸清楚,确认关键路径、边界条件之后,再把通过验证的片段组装成脚本,最后用-WhatIf验证一遍再正式运行。我踩过最贵的坑,都是跳过中间验证步骤直接删文件造成的。

另外,如果你有条件,尽早把系统自带的Windows PowerShell 5.1升级到PowerShell 7。同样是操作文件系统,PowerShell 7的默认编码是UTF-8、对中文路径更友好、管道性能也更好,而且相同的命令在Linux和macOS上也能用。一次学习,多平台复用,这笔账怎么算都划算。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 16:50:52

RunCat 365完整指南:10分钟修好任务栏猫咪卡顿与启动报错

RunCat 365完整指南:10分钟修好任务栏猫咪卡顿与启动报错 【免费下载链接】RunCat365 A cute running cat animation on your windows taskbar. 项目地址: https://gitcode.com/GitHub_Trending/ru/RunCat365 RunCat 365 是一款住在 Windows 任务栏里的轻量级…

作者头像 李华
网站建设 2026/9/17 16:50:22

基站定位原理与实战:不依赖GPS的无线测距技术

1. 基站定位不是“手机找信号塔”,而是信号传播时间的精密测量很多人第一次听说“基站定位”,脑子里立刻浮现出一个画面:手机像雷达一样,对着周围几座铁塔“扫描”,然后画个圈,标出自己在哪——这其实是个根…

作者头像 李华
网站建设 2026/9/17 16:46:30

40kHz超声波收发电路七种方案详解:从驱动到解调

简介:这份PDF文档聚焦40千赫兹超声波收发电路的实用设计,面向电子爱好者、硬件工程师以及电子设计竞赛参赛者,帮助读者快速了解多种驱动与接收方案。文档共整理了七种不同的电路实现方式,包括五种发射电路和两种接收电路&#xff…

作者头像 李华
网站建设 2026/9/17 16:46:29

OFDM与OCDM模糊函数对比:用MATLAB量化波形设计关键指标

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华