惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
博客园_首页
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
MongoDB | Blog
MongoDB | Blog
美团技术团队
H
Help Net Security
G
Google Developers Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
M
MIT News - Artificial intelligence
腾讯CDC
IT之家
IT之家
Vercel News
Vercel News
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
I
InfoQ
博客园 - 司徒正美
A
About on SuperTechFans

博客园 - Ivony...

扩展 DbUtility (1) DbUtility v3 背后的故事 DbUtility v3 Jumony Core 3,真正的HTML引擎,正式版发布 新项目,WebTest Jumony Core 2.2 发布 尝鲜Jumony for MVC,体验插件化网站开发 用网站(WebSite而不是WebProject)项目构建ASP.NET MVC网站 浅谈ASP.NET网站的编译模型和参数 C#5纯属YY的展望 Jumony for MVC现状和展望 通过源代码研究ASP.NET MVC(八) 通过源代码研究ASP.NET MVC(七) Jumony入门(四)无缝体验 Jumony入门(三)初探解析器 Jumony入门(二)初识选择器 Jumony入门(一)从这里开始 通过源代码研究ASP.NET MVC中的Controller和View(六) 通过源代码研究ASP.NET MVC中的Controller和View(五)
一段自动搜索所有SVN工作目录进行更新的PowerShell脚本
Ivony... · 2010-12-02 · via 博客园 - Ivony...

首先给出这个脚本,其实很简单,但我差不多花了四五个小时才调试成功:

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"

希望对同样很懒的你有帮助。

在这个基础上,也不难做出什么关机自动提交的脚本。。。。