PowerShell文件系统(三)导航文件系统 5


PowerShell 文件系统系列文章:

除非你通过第九章介绍的方式更改了PowerShell控制台的提示信息,否则你工作的当前目录会在控制台的命令行开头显示。你也可以使用Get-Location命令获取当前工作的目录。

Get-Location
Path
----
C:\Users\Mosser Lee\Sources

如果你想导航到文件系统的另外一个位置,可以使用Set-Location或者它的别名Cd

# 进入父目录 (相对路径):
Cd ..
# 进入当前盘的根目录 (相对路径):
Cd \
# 进入指定目录 (绝对路径):
Cd c:\windows
# 从环境变量中获取系统目录 (绝对路径):
Cd $env:windir
# 从普通变量中获取目录 (绝对路径):
Cd $home

相对路径和绝对路径

路径的指定可以是相对路径,也可以是绝对路径。在上面的最后一个例子中,兼而有之这两种路径。相对路径依赖你当前的路径,比如.\test.txt文件总是指定的是当前目录中的test.txt文件,而..\test.txt指定的是父目录的test.txt文件。相对路径通常比较实用,比如你想使用的脚本库位于当前工作目录,你就可以在不引入其它目录的情况下,直接工作。而绝对路径通常具有唯一性,并且独立于你当前的目录。

用于指定相对路径的四个重要的特殊字符

字符

意义 示例 示例描述

.

当前目录 Ii . 用资源浏览器打开当前目录

..

父目录 Cd .. 切换到父目录

\

驱动器根目录 Cd \ 切换到驱动器的顶级根目录

~

家目录 Cd ~ 切换到PowerShell初始化的目录

相对路径转换成绝对路径

当你使用相对路径时,PowerShell必须将这些相对转换成绝对路径。在你使用相对路径执行一个文件或者一条命令时,该转换会自动发生。你也可以自己使用Resolve-Path命令来处理。

PS C:\Users\Mosser> Resolve-Path .\a.png

Path
----
C:\Users\Mosser\a.png

然而,Resolve-Path命令只有在文件确实存在时,才会有效。如果你的当前文件夹中没有一个名为a.png的是,Resolve-Path名讳报错。

如果你指定的路径中包含了通配符,Resolve-Path还可以返回多个结果。下面的命令执行后,会获取PowerShell家目录下面的所有的ps1xml文件的名称。

PS> Resolve-Path $pshome\*.ps1xml

Path
----
C:\Windows\System32\WindowsPowerShell\v1.0\Certificate.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\Diagnostics.Format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\DotNetTypes.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\Event.Format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\FileSystem.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\getevent.types.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\Help.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\HelpV3.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\PowerShellCore.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\PowerShellTrace.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\Registry.format.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\types.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml
C:\Windows\System32\WindowsPowerShell\v1.0\WSMan.Format.ps1xml

像Dir一样,Resolve-Path可以在下行函数中扮演选择过滤器的的角色。下面的例子会演示在记事本中打开一个文件进行处理。命令调用记事本程序通过Resolve-Path打开这个文件。

notepad.exe (Resolve-Path  $pshome\types.ps1xml).providerpath

如果没有符合标准的文件,Resolve-Path会抛出一个异常,记录在$?变量中(第十一章),在错误发生时表达式!$?一直会统计,在True的情况下,代表可能没找到文件。

如果Resolve-Path找到了多个文件会把它保存在一个数组中,这样的化会有很多不期望的文件被打开。函数使用了第六章讲到的PowerShell 内部的函数PromptForChoice(),来请求用户做出选择。

function edit-file([string]$path=$(Throw "请输入相对路径!"))
{
# 处理相对路径,并抑制错误
$files = Resolve-Path $path -ea SilentlyContinue
# 验证是否有错误产生:
if (!$?)
{
# 如果是,没有找到符合标准的文件,给出提醒并停止:
"没有找到符合标准的文件."; 
break
}
# 如果返回结果为数组,表示有多个文件:
if ($files -is [array])
{
# 此种情况下,列出你想打开的文件:
Write-Host -foregroundColor "Red" -backgroundColor "White" `
"你想打开这些文件吗?"
foreach ($file in $files)
{
"- " + $file.Path
}

# 然后确认这些文件是否为用户想打开的:
$yes = ([System.Management.Automation.Host.ChoiceDescription]"&yes")
$no = ([System.Management.Automation.Host.ChoiceDescription]"&no")
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no)
$result = $host.ui.PromptForChoice('Open files','Open these files?',$choices,1)
# 如果用户确认,使用"&"操作符启动所有的文件
if ($result -eq 0)
{
foreach ($file in $files)
{
& $file
}
}
}
else
{
# 如果是单个文件,可以直接使用"&"启动:
& $files
}
}

保存目录位置

当前的目录可以使用Push-Location命令保存到目录堆栈的顶部,每一个Push-Location都可以将新目录添加到堆栈的顶部。使用Pop-Location可以返回。

因此,如果你要运行一个任务,不得不离开当前目录,可以在运行任务前将用Push-Location存储当前路径,然后运行结束后再使用Pop-Location返回到当前目录。Cd $home总是会返回到你的家目录,Push-Location 和 Pop-Location支持堆栈参数。这使得你可以创建很多堆栈,比如一个任务,一个堆栈。Push-Location -stack job1会把当前目录保存到job1堆栈中,而不是标准堆栈中。当然在你想重新回到这个位置时,也需要在Pop-Location中指定这个参数-stack job1。

查找特殊的目录

Windows使用了很多特殊的目录,根据系统的安装,可能稍有不同。一些非常重要的目录的路径同时也保存在Windows环境变量中,这样PowerShell 可以非常方便和清晰的访问它们。你也可以使用.NET framework中的Environment类去访问其它特殊目录。

存储在环境变量中的Windows特殊目录

特殊目录

描述 示例
Application data 存储在本地机器上的应用程序数据 $env:localappdata
User profile 用户目录 $env:userprofile
Data used incommon 应用程序公有数据目录 $env:commonprogramfiles
Public directory 所有本地用户的公有目录 $env:public
Program directory 具体应用程序安装的目录 $env:programfiles
Roaming Profiles 漫游用户的应用程序数据 $env:appdata
Temporary files(private) 当前用户的临时目录 $env:tmp
Temporary files 公有临时文件目录 $env:temp
Windows directory Windows系统安装的目录 $env:windir

环境变量返回的只是其中一部分,还不是全部的特殊目录。比如如果你想将某个文件放到一个用户的桌面,你需要的路径在环境变量中是无法获取的。但是你可以使用.NET的方法environment类下面的GetFolderPath()方法。下面会演示如何在桌面上创建一个快捷方式。

# 在桌面上创建一个快捷方式:
$path = [Environment]::GetFolderPath("Desktop") + "\EditorStart.lnk"
$comobject = New-Object -comObject WScript.Shell
$link = $comobject.CreateShortcut($path)
$link.targetpath = "notepad.exe"
$link.IconLocation = "notepad.exe,0"
$link.Save()

GetFolderPath()目录的类型可以在枚举值SpecialFolder中找到。你可以使用下面一行脚本查看它的内容。

PS> [System.Environment+SpecialFolder] | Get-Member -static -memberType Property | select -ExpandPropert
y Name
AdminTools
ApplicationData
CDBurning
CommonAdminTools
CommonApplicationData
CommonDesktopDirectory
CommonDocuments
CommonMusic
CommonOemLinks
CommonPictures
CommonProgramFiles
CommonProgramFilesX86
CommonPrograms
CommonStartMenu
CommonStartup
CommonTemplates
CommonVideos
Cookies
Desktop
DesktopDirectory
Favorites
Fonts
History
InternetCache
LocalApplicationData
LocalizedResources
MyComputer
MyDocuments
MyMusic
MyPictures
MyVideos
NetworkShortcuts
Personal
PrinterShortcuts
ProgramFiles
ProgramFilesX86
Programs
Recent
Resources
SendTo
StartMenu
Startup
System
SystemX86
Templates
UserProfile
Windows

如果你想预览所有GetFolderPath()支持的目录内容,可以使用下面的例子:

[System.Environment+SpecialFolder] |
Get-Member -static -memberType Property |
ForEach-Object { "{0,-25}= {1}" -f $_.name, [Environment]::GetFolderPath($_.Name) 
}

AdminTools               = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tool
ApplicationData          = C:\Users\mosser\AppData\Roaming
CDBurning                = C:\Users\mosser\AppData\Local\Microsoft\Windows\Burn\Burn
CommonAdminTools         = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools
CommonApplicationData    = C:\ProgramData
CommonDesktopDirectory   = C:\Users\Public\Desktop
CommonDocuments          = C:\Users\Public\Documents
CommonMusic              = C:\Users\Public\Music
CommonOemLinks           =
CommonPictures           = C:\Users\Public\Pictures
CommonProgramFiles       = C:\Program Files\Common Files
CommonProgramFilesX86    = C:\Program Files (x86)\Common Files
CommonPrograms           = C:\ProgramData\Microsoft\Windows\Start Menu\Programs
CommonStartMenu          = C:\ProgramData\Microsoft\Windows\Start Menu
CommonStartup            = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
CommonTemplates          = C:\ProgramData\Microsoft\Windows\Templates
CommonVideos             = C:\Users\Public\Videos
Cookies                  = C:\Users\mosser\AppData\Local\Microsoft\Windows\INetCookies
Desktop                  = C:\Users\mosser\Desktop
DesktopDirectory         = C:\Users\mosser\Desktop
Favorites                = C:\Users\mosser\Favorites
Fonts                    = C:\WINDOWS\Fonts
History                  = C:\Users\mosser\AppData\Local\Microsoft\Windows\History
InternetCache            = C:\Users\mosser\AppData\Local\Microsoft\Windows\INetCache
LocalApplicationData     = C:\Users\mosser\AppData\Local
LocalizedResources       =
MyComputer               =
MyDocuments              = C:\Users\mosser\Documents
MyMusic                  = C:\Users\mosser\Music
MyPictures               = C:\Users\mosser\Pictures
MyVideos                 = C:\Users\mosser\Videos
NetworkShortcuts         = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Network Shortcuts
Personal                 = C:\Users\mosser\Documents
PrinterShortcuts         = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Printer Shortcuts
ProgramFiles             = C:\Program Files
ProgramFilesX86          = C:\Program Files (x86)
Programs                 = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Recent                   = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Recent
Resources                = C:\WINDOWS\resources
SendTo                   = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\SendTo
StartMenu                = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Start Menu
Startup                  = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
System                   = C:\WINDOWS\system32
SystemX86                = C:\WINDOWS\SysWOW64
Templates                = C:\Users\mosser\AppData\Roaming\Microsoft\Windows\Templates
UserProfile              = C:\Users\mosser
Windows                  = C:\WINDOWS

构造路径

路径名称由文本构成,能让你随心所欲地构造他们。你也应当看到了上面例子中构造用户桌面快捷方式的过程了:

path = [Environment]::GetFolderPath("Desktop") + "\file.txt"
$path
C:\Users\mosser\Desktop\file.txt

一定要确保你的路径中的反斜杠个数正确。这也就是为什么前面的例子中在file.txt前面使用了一个反斜杠。还有一个更可靠的方式,就是使用命令 Join-Path方法,或者.NET中的Path静态类。

path = Join-Path ([Environment]::GetFolderPath("Desktop")) "test.txt"
$path
C:\Users\mosser\Desktop\test.txt
$path = [System.IO.Path]::Combine([Environment]::`
GetFolderPath("Desktop"), "test.txt")
$path
C:\Users\mosser\Desktop\test.txt

Path类还包含了许多用来合并或者获取目录特定信息的额外方法。你只需要在下面表格中列出的方法中前加[System.IO.Path]::,比如:

[System.IO.Path]::ChangeExtension("test.txt", "ps1")
test.ps1

构造路径的方法

方法 描述 示例
ChangeExtension() 更改文件的扩展名 ChangeExtension(“test.txt”, “ps1”)
Combine() 拼接路径字符串; 对应Join-Path Combine(“C:\test”, “test.txt”)
GetDirectoryName() 返回目录对象:对应Split-Path -parent GetDirectoryName(“c:\test\file.txt”)
GetExtension() 返回文件扩展名 GetExtension(“c:\test\file.txt”)
GetFileName() 返回文件名:对应Split-Path -leaf GetFileName(“c:\test\file.txt”)
GetFileNameWithoutExtension() 返回不带扩展名的文件名 GetFileNameWithoutExtension(“c:\test\file.txt”)
GetFullPath() 返回绝对路径 GetFullPath(“.\test.txt”)
GetInvalidFileNameChars() 返回所有不允许出现在文件名中字符 GetInvalidFileNameChars()
GetInvalidPathChars() 返回所有不允许出现在路径中的字符 GetInvalidPathChars()
GetPathRoot() 返回根目录:对应Split-Path -qualifier GetPathRoot(“c:\test\file.txt”)
GetRandomFileName() 返回一个随机的文件名 GetRandomFileName()
GetTempFileName() 在临时目录中返回一个临时文件名 GetTempFileName()
GetTempPath() 返回临时文件目录 GetTempPath()
HasExtension() 如果路径中包含了扩展名,则返回True HasExtension(“c:\test\file.txt”)
IsPathRooted() 如果是绝对路径,返回为True; Split-Path -isAbsolute IsPathRooted(“c:\test\file.txt”)

原文地址:Working with the File System

本文链接: https://www.pstips.net/navigating-the-file-system.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

5 条评论 “PowerShell文件系统(三)导航文件系统