获取在特定日期之后修改的一组文件

发布于 2024-08-06 16:41:36 字数 179 浏览 2 评论 0原文

有没有人有一个方便的 powershell 脚本,可以根据修改日期从 TFS 获取一组文件?我想说“给我这个文件夹(或子文件夹)中在 X/Y/ZZZZ 之后修改的所有文件”,并将这些文件转储到它们通常所在的文件夹之外的文件夹中。我知道足够的 powershell 来破解并最终完成这件事,但我希望避免这种情况。

Does anyone have a handy powershell script that gets a set of files from TFS based on a modification date? I'd like to say "give me all the files in this folder (or subfolder) that were modified after X/Y/ZZZZ" and dump those files to a folder other than the folder they would normally go to. I know enough powershell to hack about and get this done, eventually, but I'm hoping to avoid that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

開玄 2024-08-13 16:41:36

确保您已安装 Team Foundation 2015 Power Tools。它带有一个 PowerShell 管理单元。您可以直接从启动组运行 PowerShell 控制台文件,也可以执行 Add-PSSnapin Microsoft.TeamFoundation.PowerShell。然后 cd 到您的工作区并执行:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Format-Table CheckinDate,TargetServerItem -auto

CheckinDate           TargetServerItem 
-----------           ----------------
9/14/2009 1:29:23 PM  $/Foo/Trunk/Bar.sln                            
9/29/2009 5:08:26 PM  $/Foo/Trunk/Baz.sln       

将该信息转储到一个目录:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Select TargetServerItem > c:\recentlyChangedFiles.txt

将这些文件复制到另一个目录(假设您已将它们本地拉到工作文件夹中):

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    CopyItem -Path $_.LocalItem -Destination C:\SomeDir -Whatif

请注意,这会将文件复制到平面文件夹结构中。如果你想维护目录结构,那就有点复杂了。

Make sure you have the Team Foundation 2015 Power Tools installed. It comes with a PowerShell snapin. You can run the PowerShell console file right from its startup group or you can execute Add-PSSnapin Microsoft.TeamFoundation.PowerShell. Then cd to your workspace and execute:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Format-Table CheckinDate,TargetServerItem -auto

CheckinDate           TargetServerItem 
-----------           ----------------
9/14/2009 1:29:23 PM  $/Foo/Trunk/Bar.sln                            
9/29/2009 5:08:26 PM  $/Foo/Trunk/Baz.sln       

To dump that info to a dir:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Select TargetServerItem > c:\recentlyChangedFiles.txt

To copy those files to another dir (this assumes you have them pulled down locally into a workfolder):

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    CopyItem -Path $_.LocalItem -Destination C:\SomeDir -Whatif

Note this copies files into a flat folder structure. If you want to maintain the dir structure it is a bit more involved.

与往事干杯 2024-08-13 16:41:36

像 Keith 这样使用 Get-TfsItemProperty 不仅需要一个用于文件副本的工作空间。它是 GetExtendedItems() 的包装器,这是源代码管理资源管理器中最常见的本地信息服务器查询。通过依赖它报告的版本信息,您假设文件本身是在过去 30 天内下载的(更一般地说:同步,在重命名和删除的情况下)。如果工作区不是最新的,您将错过一些文件/给它们提供过时的名称/等等。作为信息命令,它也相当昂贵。

一些替代示例:

# 1
Get-TfsChildItem $/FilesYouWant -R | 
    ? { $_.CheckinDate -gt (Get-Date).AddDays(-30) } | 
    % { $_.DownloadFile(join-path C:\SomeDir (split-path $_.ServerItem -leaf)) }

# 2
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" |
    Select-TfsItem |
    Select -Unique -Expand Path |
    Sort |
    Out-File c:\RecentlyChanged.txt

第一个是 Keith 代码的直接改编,使用更便宜的查询并消除工作区依赖性。如果您知道该目录下的大部分项目最近被修改,那么这是最好的选择。

第二个选项直接查询变更集历史记录。通过让Where子句在SQL中而不是在客户端上计算,如果最近更改的项目百分比较低(通常是这种情况),则效率可以提高一个数量级。但是,如果返回大量大型变更集,它将滞后于基于项目的查询,从而使服务器的 JOIN 获取项目属性的成本昂贵,并迫使我们的客户端重复删除执行大量工作。

[是的,我知道 -Version 需要一个字符串并不是很 Powershell 式的;我很抱歉。您可以使用 new-object 创建一个 DateVersionSpec 并调用其 ToString(),但这需要更多工作。]

我没有展示 API 调用 + 所需任务的每种组合。不用说,您可以使用 #1 生成文件列表,并使用 #2 通过修改管道的后半部分来(重新)下载。您甚至可以将该复制技术与 Get-TfsItemHistory 的效率结合起来:

# 2b, with local-to-local copying
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" | 
    Select-TfsItem |
    Select -Unique -Expand Path |
    Get-TfsItemProperty | 
    Copy $_.LocalItem -Dest C:\SomeDir

确实,这会进行到服务器的第二次往返,但由于初始查询,GetExtendedItems() 调用的范围将限定为我们感兴趣的精确项目集当然,我们消除了下载时间成为瓶颈的任何可能性。当变更集的数量很小并且我对 Keith 工作区同步提出的担忧无论出于何种原因都不相关时,这可能是最好的解决方案。

我只能说,必须使用 powershell 来执行此操作似乎很荒谬。

FWIW,我从内部参与了 TFS 的工作。在 MS 之外工作了 4.5 年,从未见过此功能请求。如果您可以详细说明您实际想要实现的目标,我猜我们可以提出更好的方法。不要误会我的意思,我编写 Powershell 扩展正是为了处理这样的奇怪场景。但通常这完全是另一个工具的工作,例如:注释、MSBuild、数据库模式比较......

Using Get-TfsItemProperty like Keith doesn't just require a workspace for the file copies. It's the wrapper for GetExtendedItems(), the server query for local info most commonly seen in Source Control Explorer. By relying on the version info it reports, you assume the files themselves were downloaded (more generally: synchronized, in the case of renames & deletes) in the last 30 days. If the workspace is not up to date, you'll miss some files / give them out-of-date names / etc. It's also quite expensive as informational commands go.

Some alternative examples:

# 1
Get-TfsChildItem $/FilesYouWant -R | 
    ? { $_.CheckinDate -gt (Get-Date).AddDays(-30) } | 
    % { $_.DownloadFile(join-path C:\SomeDir (split-path $_.ServerItem -leaf)) }

# 2
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" |
    Select-TfsItem |
    Select -Unique -Expand Path |
    Sort |
    Out-File c:\RecentlyChanged.txt

The first is a straightforward adaptation of Keith's code, using a cheaper query and eliminating the workspace dependency. It's the best option if you know a high % of the items under that dir were modified recently.

The second option queries the changeset history directly. By letting the Where clause be computed in SQL instead of on the client, this can be an order of magnitude more efficient if a low % of the items were changed recently (as is often the case). However, it will lag the item-based queries if there are lots of large changesets returned, making the server's JOIN to grab the item properties expensive and forcing our client-side duplicate removal to do a lot of work.

[Yes, I know that having -Version require a string is not very Powershell-esque; mea culpa. You could create a DateVersionSpec with new-object and call its ToString(), but that's even more work.]

I didn't show every combination of API call + desired task. Goes without saying you can use #1 to generate the file list and #2 to (re)download by modifying the latter half of the pipeline. You can even combine that copy technique with the efficiency of Get-TfsItemHistory:

# 2b, with local-to-local copying
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" | 
    Select-TfsItem |
    Select -Unique -Expand Path |
    Get-TfsItemProperty | 
    Copy $_.LocalItem -Dest C:\SomeDir

It's true this makes a 2nd roundtrip to the server, but thanks to the initial query the GetExtendedItems() call will be scoped to the precise set of items we're interested in. And of course we remove any chance that download time becomes the bottleneck. This is likely the best solution of all when the # of changesets is small and the concerns I raised about Keith's workspace synchronization aren't relevant for whatever reason.

Can I just say that having to user powershell to do this seems absurd.

FWIW, I've been involved with TFS from inside & outside MS for 4.5yr and never seen this feature requested. If you could expand on what goal you're actually trying to accomplish, my guess is we could suggest a better way. Don't get me wrong, I wrote the Powershell extensions precisely to handle oddball scenarios like this. But frequently it's a job for another tool entirely, eg: Annotate, MSBuild, DB schema compare...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文