简体   繁体   English

检查 100k 文件的修改年龄 --> PathTooLongException

[英]Check Modify Age of 100k files --> PathTooLongException

currently I am working on a script that should give me the number of files that have been modified in the last 30 days or between 30 and 180 days or that have not been modified for 180 days.目前我正在编写一个脚本,该脚本应提供过去 30 天或 30 到 180 天内修改过的文件数或 180 天内未修改的文件数。 So three queries in total, everything gets its own variable in which the count is stored.所以总共三个查询,每个查询都有自己的变量,其中存储了计数。 The whole thing should be executed on several remote servers.整个事情应该在几个远程服务器上执行。

However, the folder structure on these servers is very deep and PowerShell regularly hits the 260 character limit (PathTooLongException).但是,这些服务器上的文件夹结构非常深,PowerShell 经常达到 260 个字符的限制(PathTooLongException)。

The following is the script:以下是脚本:

$servers = "server1", "server2"

$folder = "\Path\to\folder\"

foreach ($server in $servers) {
    
  $session = New-PSSession -ComputerName $server

  $folder_30 = Invoke-Command -Session $session -ScriptBlock {
    (Get-ChildItem -LiteralPath $using:folder -Recurse -File | where{$_.LastWriteTime -ge (Get-Date).AddDays(-30)}).count
  }

  $folder_30_180 = Invoke-Command -Session $session -ScriptBlock {
    (Get-Childitem -LiteralPath $using:folder -Recurse -File | where{$_.LastWriteTime -ge (Get-Date).AddDays(-180) -AND $_.LastWriteTime -lt (Get-Date).AddDays(-30)}).count
  }

  $folder_180 = Invoke-Command -Session $session -ScriptBlock {
    (Get-Childitem -LiteralPath $using:folder -Recurse -File | where{$_.LastWriteTime -lt (Get-Date).AddDays(-180)}).count
  }

Remove-PSSession $session
}

Is there a way to change the script so that the "PathTooLongException" error no longer occurs?有没有办法更改脚本以便不再出现“PathTooLongException”错误? Would it be an option to change the script so that it first jumps to the lower levels and only then executes the "Get-ChildItem" and count cmdlt and how would I do that?是否可以选择更改脚本,使其首先跳转到较低级别,然后才执行“Get-ChildItem”并计算 cmdlt,我该怎么做? Or is there a more elegant solution?或者有更优雅的解决方案吗?

Thanks in advance:)提前致谢:)

Edit: the remote servers are running win server 2012编辑:远程服务器正在运行 win server 2012

Edit 2: I found a solution which is not perfect and takes like twice as long, but I can avoid the PathTooLongException ;编辑 2:我找到了一个不完美的解决方案,需要两倍的时间,但我可以避免 PathTooLongException You can use the following code snippet:您可以使用以下代码片段:

Get-Childitem -LiteralPath \\?\UNC\SERVERNAME\folder\

This didn't work with the Invoke-Command on the remote servers because they are running an old PowerShell version, but I was able to use this command and remotely connect from a Win 2016. Not perfect, but it works ¯_(ツ)_/¯这不适用于远程服务器上的Invoke-Command ,因为它们运行的是旧的 PowerShell 版本,但我能够使用此命令并从 Win 2016 远程连接。不完美,但它有效 ¯_(ツ) _/¯

This link helped me: https://c-nergy.be/blog/?p=15339这个链接帮助了我: https://c-nergy.be/blog/?p=15339

You could probably do faster using Robocopy.使用 Robocopy 可能会做得更快。

Suppose the local path on each server is 'C:\Somewhere\folder', then for each server you need to use the UNC path \\servername\C$\Somewhere\folder .假设每个服务器上的本地路径是“C:\Somewhere\folder”,那么对于每个服务器,您需要使用 UNC 路径\\servername\C$\Somewhere\folder
The easiest way of doing that is to create a template folder path where only the servername needs to be inserted:最简单的方法是创建一个模板文件夹路径,只需要插入服务器名:

$servers = "server1", "server2"
$folder  = '\\{0}\C$\Somewhere\folder'   # template UNC path whwere te servername or IP is inserted

foreach ($server in $servers) {
    $path = $folder -f $server
    $allFiles = @((robocopy $path NULL /L /E /NP /XJ /NC /NS /NDL /NJH /NJS /TS /R:0 /W:0) -replace '^\s+' -ne ''  | 
                  Select-Object @{Name = 'LastWriteTime'; Expression = {([datetime]($_ -split "`t")[0]).ToLocalTime()}},
                                @{Name = 'FullName'; Expression = {($_ -split "`t")[1]}})

    # get the number of files newer than 30 days ago
    $date = (Get-Date).AddDays(-30).Date
    $folder_30 = ($allFiles | Where-Object { $_.LastWriteTime -ge $date }).Count

    # get the number of files older than 180 days ago
    $date = (Get-Date).AddDays(-180).Date
    $folder_180 = ($allFiles | Where-Object { $_.LastWriteTime -lt $date }).Count

    # output an object with the properties needed
    [PsCustomObject]@{
        ComputerName        = $env:COMPUTERNAME
        Path                = $path
        AllFiles            = $allFiles.Count
        NewerThan30Days     = $folder_30
        OlderThan180Days    = $folder_180
        Between30And180Days = $allFiles.Count - $folder_30 - $folder_180
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM