您的位置:首页 > 运维架构 > Shell

自动搜索所有SVN工作目录进行更新的PowerShell脚本

2010-12-03 09:51 381 查看
首先给出这个脚本:

dir -r |?{ $_.Mode -like
"*d*"} |cd -passthru |?{ (gci -force |%{ $_ -as [string] }) -contains
".svn" } |%{gl; svn cleanup; svn update }

解释:

dir –r

dir是Get-ChildItem的别名,这里的-r是-Recurse的缩写,PowerShell脚本所有参数和命令都不区分大小写,并且在没有歧义的前提下可以缩写。

这个指令的含义就是获取当前位置(省略-Path参数默认就是当前目录)所有子项,并且递归获取子项的子项。也就是类似于dir /s的效果,只不过这里会返回这些项(文件或目录)供后面的使用而不是显示在屏幕上了事。

然后是|?{ $_.Mode –like “*d*” }

|是管道操作符,意思是把前面指令的输出当作后面指令的输入,后面的指令是?,这个?是Where-Object的别名,所以其实你可以写成这样:

Get-ChildItem | Where-Object { …

当然这样太罗嗦了。Where-Object有很多参数,帮助中是这样说的:

Where-Object [-FilterScript] <scriptblock> [-InputObject <psobject>] [<CommonParameters>]


中 –InputObject
这个参数是管道输入,换言之通过管道运算符传来的东西会被自动当成这个参数后面的<psoobject>,每个PowerShell的指令的
输入参数都不同,你可以通过help where-object –full看到这些信息:

......

-InputObject <psobject>

指定要筛选的对象。还可将对象通过管道传递给 Where-Object。

是否必需? False

位置? named

默认值

是否接受管道输入? true (ByValue)

是否接受通配符? False

......

注意这里的是否接受管道输入是true,有些PowerShell指令有多个接受管道输入的参数,那他们一般都会是互斥的。

OK,现在我们知道dir -r的结果会被当作Where-Object的-InputObject参数了,这个Where-Object的主要用途就是从输入中筛选符合条件的项,这里的筛选脚本是花括号里面括起来的东西:

{ $_.Mode –like “*d*” }

$_代表迭代的每一项,也就是dir -r结果里面的每一项,那么这里是判断每一项的Mode属性是不是包含一个”d”字符,也就是这个东西是不是目录。

筛选后的结果会被发送给|cd -passthru

cd
是Set-Location的别名,也就是改变当前工作目录。结合前面的脚本,这里等于会让PowerShell到当前目录的所有子目录去跑一圈,不过如
果只是跑一圈不干活那这个脚本是什么意义都没有的。所以cd带了一个参数叫做
-passthru。这个参数的意思是在执行完改变工作目录的操作后,把输入继续抛到后面去执行。

那么后面是最关键的部分了:

|?{ (gci -force |%{ $_ -as [string] }) -contains ".svn" }

这里又是一个Where-Object筛选,它执行的脚本是:

{ (gci -force |%{ $_ -as [string] }) -contains ".svn" }


点点来解释,gci是Get-ChildItem的另一个别名(一开始的dir也是Get-ChildItem),-force参数告诉gci就算是隐藏
的项也要取出来。请注意这里的gci被包在了{}脚本块里面,所以他没有什么管道输入,和一开始的dir一样,他是用空的-Path参数来执行的,换言之
这里的gci其实就是gci . -force。由于前面有一个cd操作,所以这里的.会是所有的子目录。

也就是说:

第一个dir -r结合筛选会获取当前目录所有子代目录,

然后cd -passthru会改变工作目录到每一个子代

在每一个子代,又都会执行gci来获取所有子文件(目录)。

gci
的结果被管道到%{ $_ -as [string]
},%是ForEach-Object的别名,ForEach-Object和Where-Object类似,只不过Where-Object是对每一项
执行一个判断,只返回符合条件的项,而ForEach-Object是对每一项执行一个操作返回操作结果,也就类似于LINQ是select和where
的区别。

这个操作是 -as [string]也就是把项变成字符串,也就是文件名(目录名)

(gci |%{ $_ -as [string] })

经过这个复杂的操作后,gci的结果就由文件(目录)集合变成了字符串集合,这个时候再对其执行 -contains ".svn",判断这个字符串集合里面有没有".svn"这样的字符串。换言之,有没有名为.svn的文件或目录。

所以{ (gci |%{ $_ -as [string] }) -contains ".svn" }这个脚本的结果就是,这个目录的子文件(目录)包不包含".svn",因为只有包含.svn的才是svn的工作目录。

接下来执行的操作就比较简单了:

|%{gl; svn cleanup; svn update }

对于筛选出来的结果(此时结果已经不重要了,因为已经通过cd设置为了工作位置,所以里面没有$_了)执行一段脚本。

gl是Get-Location的缩写,也就是获取当前的位置,执行这个操作主要是为了显示一下当前在哪个目录干活。

然后执行svn cleanup和svn update。

最后我把这些操作写成了一个VS的启动脚本,这样每次通过这个脚本启动VS就能确保我的项目都是最新的了:

$logsfile = ("$home/Documents/svn-update-logs", (get-date -format "yyyyMMddHHmmss") -join "/") , "log" -join "."

pushd

cd 'C:/Users/Ivony/Documents/Visual Studio 2010/Projects'

dir
-r |?{ $_.Mode -like "*d*"} |cd -passthru |?{ (gci -force |%{ $_ -as
[string] }) -contains ".svn" } |%{gl; svn cleanup; svn update } | tee
$logsfile

popd

echo "completed." | tee $logsfile

echo "logs file: $logsfile"

echo "starting IDE"

ii "C:/Program Files/Microsoft Visual Studio 10.0/Common7/IDE/devenv.exe"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐