【问题标题】:Powershell delete 6 days old folderPowershell删除6天前的文件夹
【发布时间】:2014-07-15 12:19:15
【问题描述】:

我必须制作 PS 脚本才能将其与我们的自动化软件集成。我是PS的初学者,我做了一些尝试,但仍然没有成功。这是我的任务。 我有一个将用作输入参数的参数。那将是远程磁盘路径 %setupRootPath%。该目录有多个子目录,例如(Beta、Testing、Release 等)每个子目录都有项目名称。在持续集成系统中,每个项目都获得 Build Nomber,所以最后我得到了类似

  • %setupRootPath%\Beta\ProjektA\Build1000
  • %setupRootPath%\Beta\ProjektA\Build1003
  • %setupRootPath%\Beta\ProjektA\Build1004
  • %setupRootPath%\Beta\ProjektB\Build1007
  • %setupRootPath%\Beta\ProjektB\Build1008
  • %setupRootPath%\Beta\ProjektB\Build1009
  • %setupRootPath%\Beta\ProjektB\Build10010
  • %setupRootPath%\SystemTesting\ProjektA\Build1002

目前有数百个项目,我编写了 C# 代码来实现我想要的,但如果我可以通过 PS 而不是 C# 使用调度程序运行它会很棒

这里是 C# 代码

class Program
{
    const string rootDirPath = @"\\pcName\AutomationProcess\Deployment";
    const int keepNum = 1;
    const int deployDepth = 2;

    static void Main(string[] args)
    {
        var delDir = new DirectoryInfo(rootDirPath);
        var currentDateTime = DateTime.Now;

        int currentDetph = 0;
        var deployPathes = new Dictionary<DirectoryInfo, int>();
        GetDeployDirectories(delDir, currentDetph, deployPathes);

        foreach (var projektDir in deployPathes.Keys)
        {
            var dirInfoArray = projektDir.GetDirectories();
            if (dirInfoArray != null)
            {
                var sortedDeploymentDirs = from d in dirInfoArray
                                           where (currentDateTime - d.LastWriteTime).Days > 6
                                           orderby d.LastWriteTime
                                           select d;
                var deploymentDirsArray = sortedDeploymentDirs.ToArray();
                if (deploymentDirsArray.Length > keepNum)
                {
                    for (int i = 0; i < deploymentDirsArray.Length - keepNum; i++)
                    {
                        Console.WriteLine("Delete: {0}", deploymentDirsArray[i].FullName);
                    }
                }
            }
        }
    }

    private static void GetDeployDirectories(DirectoryInfo currentDirectory, int currentDetph, Dictionary<DirectoryInfo, int> resultDictionary)
    {
        currentDetph++;

        foreach (DirectoryInfo subDir in currentDirectory.GetDirectories())
        {
            if (currentDetph < deployDepth)
            {
                subDir.Refresh();
                GetDeployDirectories(subDir, currentDetph, resultDictionary);
            }
            else if (currentDetph == deployDepth)
            {
                resultDictionary.Add(subDir, currentDetph);
            }
        }
    }
}

我无法删除所有旧文件,我必须删除所有超过 6 天的文件,但保留最后一个版本,即使它较旧。

所以删除后我应该得到例如这样的结果

  • %setupRootPath%\Beta\ProjektA\Build1000(已删除)
  • %setupRootPath%\Beta\ProjektA\Build1003(已删除)
  • %setupRootPath%\Beta\ProjektA\Build1004(如果删除则较旧,然后没有,跳过)
  • %setupRootPath%\Beta\ProjektB\Build1007(已删除)
  • %setupRootPath%\Beta\ProjektB\Build1008(已删除)
  • %setupRootPath%\Beta\ProjektB\Build1009(不超过 6 天,已跳过)
  • %setupRootPath%\Beta\ProjektB\Build10010(不超过 6 天,已跳过)
  • %setupRootPath%\SystemTesting\ProjektA\Build1002(较旧但只有一个,已跳过)

我明天试试。但如果有人会帮忙。我会很高兴的:) 下面是我目前的状态。 它有效,但只有当我提供整个 Projekt 文件时,而不是只提供根目录;(

param([String] $delpath=\\pcName\AutomationProcess\Deployment\Beta\ProjektA\",[String] $keepNum="1")
function Get-SubDirDate($directory)
{
    $datetime = $directory.LastWriteTime
    $SubDirDatealldir = gci $directory.FullName -filter * | ? { $_.PSisContainer -eq $true} 
    $SubDirDatealldir = @($SubDirDatealldir)
    foreach ($subdir in $SubDirDatealldir)
    {
        $subdir = $subdir -as [system.io.directoryinfo]

        if ($subdir)
        {
            $days = $subdir.LastWriteTime

            if ($days -ge $datetime)
            {
                $datetime = $days
            }
        }
    }
    $datetime
}

cd $delpath
$localdir = get-location
if ($localdir.Path.IndexOf($delpath) -ne -1)
{
    $datehash = @{}
    $CurrentTime = Get-Date

    # Mach es rekursive ;(

    $alldir = gci -filter * | ? { $_.PSisContainer -eq $true}
    $alldir = @($alldir)

    foreach ($dir in $alldir)
    {
        $dir = $dir -as [system.io.directoryinfo]
        $dir.Refresh()

        if (($dir) -and ($dir.Exists))
        {
            if (!$datehash.ContainsKey($dir.FullName))
            {
                $datehash[$dir.FullName] = Get-SubDirDate $dir
            }
        }
    }

    # Alle Verz. Aelter als 6 Tage bis auf die letzten n(=keepNum) loeschen 
    $itemCount = $datehash.Count

    if ($itemCount -gt ([int]$keepNum))
    {
        # Hash-Array nach Zeitstempel (=Value) absteigend sortieren 
        # (d.h. neuster Eintrag ist erstes Element) und die neusten n Faelle 
        # rausnehmen, damit diese nachfolgend nicht geloescht werden.             
        $datehashSorted = $datehash.GetEnumerator() | 
            Sort-Object Value -Descending | select-object -Last ($itemCount - [int]$keepNum)

        # Alle übrigen, die Älter als 6 Tage sind, löschen   
        $datehashSorted | foreach-object {

            $dir = $_.Name -as [system.io.directoryinfo] 
            $diffdays = ($CurrentTime-$_.Value).Days

            if ($diffdays -ge 6)
            {
               Write-Host ($dir.fullname)
               $dir.Delete($true) 
            }
        }
    }
}

【问题讨论】:

  • 如果你已经有一个 C# 中的工作程序,为什么不直接从你的 powershell 脚本中调用它呢?
  • 用于功能更改。更改用 TeamCity Step 编写的脚本比维护 C# 代码和应用程​​序更容易

标签: c# powershell automation teamcity


【解决方案1】:

我想这就是你所追求的。从代码的角度来看,您当然可以提高效率,或者轻松地将其转换为函数,但我试图使其可读。

# Your input parameter
$setupRootPath = "\\pcName\AutomationProcess\Deployment\"

# Retrieve the top level directories (Beta, Testing, Release, etc.).
Get-ChildItem $setupRootPath | Where-Object {$_.PSisContainer -eq $true} | ForEach-Object {
    $topDir = $_

# Pull the list of projects in the current top level dir.
    Get-ChildItem $topDir | Where-Object {$_.PSisContainer -eq $true} | ForEach-Object {
        $projectDir = $_

#Get the list of build folders, sorting by LastWriteTime, skipping the most recent, where the file is older than 6 days; and delete the remaining items.
        Get-ChildItem $projectDir | Where-Object {$_.PSisContainer -eq $true} | Sort-Object LastWriteTime -Descending | Select-Object -Skip 1 | Where-Object {((Get-Date)-$_.LastWriteTime).TotalDays -gt 6} | Remove-Item

    }
}

【讨论】:

  • 非常感谢。所以当我输入这个 |选择对象-跳过 1 | Select-Object -Skip $keepNum 也应该可以工作。但是使用此解决方案,我无法配置构建项目的深度。无论如何,我今天会尝试一下。再次非常感谢你:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多