powershell访问文件和目录的方法
使用Get-ChildItem列出目录的内容。预定义的别名为Dir和ls,Get-ChildItem执行了一些很重要的任务:
显示目录内容
递归地搜索文件系统查找确定的文件
获取文件和目录的对象
把文件传递给其它命令,函数或者脚本
注意:因为Windows管理员一般在实践中,使用Get-ChildItem的别名Dir,所以接下来的例子都会使用Dir。另外ls(来自UNIX家族)也可以代替下面例子中的Dir或者Get-ChildItem。
一、powershell列出目录的内容
一般情况下,你可能只想知道在一个确定的目录中有什么文件,如果你不指定其它参数。Dir会列出当前目录的内容。如果你在Dir后跟了一个目录,它的内容也会被列出来,如果你使用了-recurse参数,Dir会列出所有子目录的内容。当然,也允许使用通配符。
例如,列出当前目录下的所有Powershell脚本,输入命令:
Dir *.ps1
Dir甚至能支持数组,能让你一次性列出不同驱动器下的内容。
下面的命令会同时列出PowerShell根目录下的PowerShell脚本和Windows根目录下的所有日志文件。
Dir $pshome*.ps1, $env:windir*.log
如果只对一个目录下的项目名称感兴趣,使用-Name参数,Dir就不会获取对象(Files和directories),只会以纯文本的形式返回它们的名称。
Dir -name
注意:一些字符在PowerShell中有特殊的意义,比如方括号。方括号用来访问数组元素的。这也就是为什么使用文件的名称会引起歧义。当你使用-literalPath参数来指定文件的路径时,所有的特殊字符被视为路径片段,PowerShell解释器也不会处理。
注:Dir 默认的参数为-Path。假如你当前文件夹下有个文件名为“.a[0].txt“,因为方括号是PowerShell中的特殊字符,会解释器被解析。为了能正确获取到”.a[0].txt”的文件信息,此时可以使用-LiteralPath参数,它会把你传进来的值当作纯文本。
PS> Get-ChildItem .a[0].txt
PS> Get-ChildItem -Path .a[0].txt
PS> Get-ChildItem -LiteralPath .a[0].txt
Directory: C:Usersmosser
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2014/1/2 14:04 80370 a[0].txt
二、powershell递归搜索整个文件系统
当搜索整个子目录时,可以使用-recurce参数。但是注意,下面例子执行时会失败。
Dir *.ps1 -recurse
你需要了解一点-recurse如何工作的细节来理解为什么会发生上面的情况。Dir总是会获取目录中的内容为文件对象或者目录对象。如果你设置了-recurse开关,Dir会递归遍历目录对象。但是你在上面的例子中使用的通配符只获取扩展名为ps1的文件,没有目录,所以-recurse会跳过。这个概念刚开始使用时可能有点费解,但是下面的使用通配符例子能够递归遍历子目录,正好解释了这点。
在这里,Dir获取了根目录下所有以字母“D”打头的项目。递归开关起了作用,那是因为这些项目中就包含了目录。
Dir $homed* -recurse
荔非苔注:原文的作者写这篇文章时,是基于PowerShell 2.0,在高版本中的PowerShell 中Dir *.ps1 -recurse也是可以工作的。
三、powershell进行目录过滤和排除标准
现在回到刚开始问题,怎样递归列出同类型的所有文件,比如所有PowerShell scripts。答案是使用Dir完全列出所有目录内容,同时指定一个过滤条件。Dir现在可以过滤出你想要列出的文件了。
除了-filter,还有一个参数乍一看和-filter使用起来很像: -include
你会看到这一戏剧性的变化,-filter的执行效率明显高于-include:
其原因在于-include支持正则表达式,从内部实现上就更加复杂,而-filter只支持简单的模式匹配。这也就是为什么你可以使用-include进行更加复杂的过滤。比如下面的例子,搜索所有第一个字符为A-F的脚本文件,显然已经超出了-filter的能力范围。
与-include相反的是-exclude。在你想排除特定文件时,可以使用-exclude。不像-filter,-include和-exclude还支持数组,能让你获取你的家目录下所有的图片文件。
做到一点即可:不要混淆了-filter 和 -include。选择这两个参数中的其中一个:具体为当你的过滤条件没有正则表达式时,使用-filter,可以显著提高效率。
注意:你不能使用filters在Dir中,列出确定大小的文件列表。因为Dir的限制条件只在文件和目录的名称级别。如果你想使用其它标准来过滤文件,可以尝试第五章中讲到的Where-Object。
下面的例子会获取你家目录下比较大的文件,指定文件至少要100MB大小。
如果你想知道Dir返回了多少个文件项,Dir会将结果保存为一个数组,你可以通过数组的的Count属性来读取。下面的命令会告诉你你的家目录下有多少图片文件(这个操作可能会比较耗时)。
五、powershell获取文件和目录的内容
你可以使用Dir直接获取一个单独的文件,因为Dir会返回一个目录下所有的文件和目录对象。
获到这个文件的FileInfo信息:
$file = Dir C:a.html
$file | Format-List *
PSPath : Microsoft.PowerShell.CoreFileSystem::C:a.html
PSParentPath : Microsoft.PowerShell.CoreFileSystem::C:
PSChildName : a.html
PSDrive : C
PSProvider : Microsoft.PowerShell.CoreFileSystem
PSIsContainer : False
VersionInfo : File: C:a.html
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
BaseName : a
Mode : -a---
Name : a.html
Length : 227740
DirectoryName : C:
Directory : C:
Isreadonly : False
Exists : True
FullName : C:a.html
Extension : .html
CreationTime : 2013/11/12 19:29:16
CreationTimeUtc : 2013/11/12 11:29:16
LastAccessTime : 2013/11/12 19:29:16
LastAccessTimeUtc : 2013/11/12 11:29:16
LastWriteTime : 2013/11/12 19:29:24
LastWriteTimeUtc : 2013/11/12 11:29:24
Attributes : Archive
可以访问单个文件的属性,如果它们的属性支持更改,也可以更改。
Get-Item是访问单个文件的另外一个途径, 下面的3条命令都会返回同样的结果:你指定的文件的文件对象。
但是,在访问目录而不是文件时,Get-Childitem 和 Get-Item表现迥异。
# Dir 或者 Get-Childitem 获取 一个目录下的内容:
$directory = Dir c:windows
$directory = Get-Childitem c:windows
$directory
Directory: C:windows
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/8/22 23:36 addins
d---- 2013/8/22 23:36 ADFS
d---- 2013/8/22 23:36 AppCompat
d---- 2013/11/22 19:13 apppatch
d---- 2013/12/27 12:05 AppReadiness
d-r-- 2013/12/17 3:44 assembly
d---- 2013/9/16 10:11 AUInstallAgent
d---- 2013/8/22 23:36 Boot
d---- 2013/8/22 23:36 Branding
d---- 2013/10/24 14:27 Camera
1
2
3
# Get-Item 获取的是目录对象本身:
$directory = Get-Item c:windows
$directory
Directory: C:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/11/22 19:13 windows
PS> $directory | Format-List *
PSPath : Microsoft.PowerShell.CoreFileSystem::C:windows
PSParentPath : Microsoft.PowerShell.CoreFileSystem::C:
PSChildName : windows
PSDrive : C
PSProvider : Microsoft.PowerShell.CoreFileSystem
PSIsContainer : True
BaseName : windows
Mode : d----
Name : windows
Parent :
Exists : True
Root : C:
FullName : C:windows
Extension :
CreationTime : 2013/8/22 21:36:15
CreationTimeUtc : 2013/8/22 13:36:15
LastAccessTime : 2013/11/22 19:13:22
LastAccessTimeUtc : 2013/11/22 11:13:22
LastWriteTime : 2013/11/22 19:13:22
LastWriteTimeUtc : 2013/11/22 11:13:22
Attributes : Directory
向命令,函数和文件脚本传递文件
因为Dir的结果中返回的是独立的文件或目录对象,Dir可以将这些对象直接交付给其它命令或者你自己定义的函数与脚本。这也使得Dir成为了一个非常重要的的选择命令。使用它你可以非常方便地在一个驱动盘下甚至多个驱动盘下递归查找特定类型的所有文件。
要做到这点,在管道中使用Where-Object来处理Dir返回的结果,然后再使用ForEach-Object(第五章),或者你自定义的管道过滤(第九章)。
小知识:你还可以将多个Dir 命令执行的结果结合起来。在下面的例子中,两个分开的Dir命令,产生两个分开的文件列表。然后PowerShell将它们结合起来发送给管道进行深度处理。这个例子获取Windows目录和安装程序目录下的所有的dll文件,然后返回这些dll文件的名称,版本,和描述:
因为Dir获取的文件和目录是一样的,有时限制结果中只包含文件或者只包含目录很重要。有很多途径可以做到这点。
可以验证返回对象的属性,PowerShell PSIsContainer属性,或者对象的类型。
前面的例子(识别对象类型)是目前速度最快的,而后面的(文本比较)比较复杂和低效。
Where-Object也可以根据其它属性来过滤。
比如下面的例子通过管道过滤2007年5月12日后更改过的文件:
也可以使用相对时间获取2周以内更改过的文件: