Skip Ribbon Commands
Skip to main content

Ondrej Sevecek's Blog

:

Engineering and troubleshooting by Directory Master!
Ondrej Sevecek's Blog > Posts > Vyhledání adresářů, které se už dlouho nezměnily
červenec 20
Vyhledání adresářů, které se už dlouho nezměnily

Problém - máme file server a potřebujeme najít všechny adresáře, jejichž obsah se už dlouho nezměnil. Použijeme k tomu samozřejmě PowerShell. Vyhledat dlouho nezměněné soubory není vůbec problém, stačí porovnat jejich atribut LastWriteTime. Jenže tohle nechceme, bude toho obvykle (sto)(deseti)tisíce, prostě mnoho. Já chci vidět jen adresář, jehož celý obsah má poslední modifikaci starší, než například 410 dnů.

Takže zde je funkce, která prohledá celou adresářovou strukturu a vrátí jen adresáře, jejichž žádný soubor se nezměnil nedávno, než před nějakým počtem dnů.

function Get-FsAgeMap (
  [Parameter(Position=0, Mandatory=$true)] [ValidateScript({ Test-Path $fsRoot })] [string] $fsRoot,
  [Parameter(Position=1)]                  [ValidateScript({ $_ -ge 0 })] [int] $ageDaysAtLeast = 0,
                                                                          [switch] $returnOnlyParent
  )
{
  if ($returnOnlyParent -and ($ageDaysAtLeast -eq 0)) {

    throw 'You must specify some minimum days of age to use the -returnOnlyParent parameter'
  }

  $fsRoot = $fsRoot.TrimEnd('\')

  [hashtable] $ageMap = @{}
  [bool] $uncFsRoot = $fsRoot -like '\\?*\?*'

  # Note: using -Force parameter in order to obtain System and Hidden files as well
  dir $fsRoot -Recurse -Force | ? { -not $_.PsIsContainer } | % { 

    [IO.FileInfo] $oneFile = $_
    [int] $ageDays = ([DateTime]::Now - $oneFile.LastWriteTime).TotalDays

    [string] $onePath = $oneFile.FullName
    while ($true) {

      [string] $onePath = Split-Path -Parent $onePath

      if ((-not ([string]::IsNullOrEmpty($onePath))) -and ($onePath.Length -ge $fsRoot.Length)) {

        if ($ageMap.ContainsKey($onePath)) {

          $ageMap[$onePath] = [Math]::Min($ageDays, $ageMap[$onePath])

        } else {

          [void] $ageMap.Add($onePath, $ageDays)
        }
      
      } else {

        break
      }
    }
  }

  if ($ageDaysAtLeast -gt 0) {

    [Collections.ArrayList] $ageMapKeys = $ageMap.Keys
    foreach ($oneAgeMapKey in $ageMapKeys) {

      if ($ageMap[$oneAgeMapKey] -lt $ageDaysAtLeast) {

        [void] $ageMap.Remove($oneAgeMapKey)
      }
    }

    if ($returnOnlyParent) {

      [Collections.ArrayList] $ageMapKeys = $ageMap.Keys
      $ageMapKeys.Sort()

      [int] $i = 0
      while ($i -lt $ageMapKeys.Count) {

        [string] $oneAgeMapKey = $ageMapKeys[$i]
        $i ++

        while (($i -lt $ageMapKeys.Count) -and ($ageMapKeys[$i] -like (Join-Path $oneAgeMapKey '?*'))) {

          [void] $ageMap.Remove($ageMapKeys[$i])
          $i ++
        }
      }
    }
  }

  return $ageMap
}

Zavoláte to jednoduše, buď s pomocí lokální cesty, nebo pomocí UNC síťové cesty, to je jedno. Parametr returnOnlyParent způsobí, že ve výsledku budou opravdu jen ty nejvrchnější adresáře. Pokud byste to tam nedali, tak by to vrátilo všechny adresáře, jejichž obsah je starší než zadaný počet dnů, takže by tam jedna podcesta byla zbytečně vícekrát. Například takto:

$ageMap = Get-FsAgeMap -fsRoot '\\fs1\profiles' -ageDaysAtLeast 210 -returnOnlyParent

 

Comments

Chybka

Nemá validace na začátku být spíš takto Test-Path $_ místo Test-Path $fsRoot
ZbR on 20.7.2016 19:09

nejvetsi slozky

na vyhledani nejvetsich slozek je super tenhle programek (neni treba instalovat, je to 1x exe) "Scanner"
http://www.steffengerlach.de/freeware/

ukase pekne kolacove grafy, nahore je videt, kde prave jste a kolik dat tam je a da se proklikat dale do hloubky.
bylo by super, kdyby takhle ukazoval i stari souboru
VasekB on 20.7.2016 22:19

statistiky

na statistiky stari+velikost+pocet souboru pouzivam "robocopy /L", kterym slozku/disk "prekopiruji" jinam a ulozim do souboru LOG z teho kopirovani. ten pak scriptem preparsuji a dostanu CSV: datum,velikost, cesta,soubor... to pak nahodim do Excelu, kde mi to vyplivne kontingencni tabulku+graf, kde je pekne videt, jak data postupne (vetsinou exponencialne ;o) rostou a ve kterych slozkach.

vyhoda tohoto reseni je, ze pomoci "robocopy /B" (+poustet pod Adminem) se dostanu i k souborum, ke kterym treba ani jako Admin nemam nastavena prava ;o))
VasekB on 20.7.2016 22:24

Script na mazání

Ahojte, nemáte někdo skript (nejlépe Powershell) případně utilitu (aby se to dělalo automaticky), který proskenuje celý sdílený disk a smaže všechny složky a soubory starší 14 dní? Osobně jsem něco zkoušel, ale vždy se nesmazalo úplně všechno.
mateo22 on 1.11.2016 12:26

Script na mazání

Ahojte, nemáte někdo skript (nejlépe Powershell) případně utilitu (aby se to dělalo automaticky), který proskenuje celý sdílený disk a smaže všechny složky a soubory starší 14 dní? Osobně jsem něco zkoušel, ale vždy se nesmazalo úplně všechno.
mateo22 on 1.11.2016 12:40

Re: Vyhledání adresářů, které se už dlouho nezměnily

něco třeba takto:

dir E:\soubory -Recurse | ? { $_.LastWriteTime -lt (Get-Date).AddMonths(-3) } | % { write-host $_.FullName }
ondass on 7.11.2016 22:29

Add Comment

Title


Pole Title nemusíte vyplňovat, doplní se to samo na stejnou hodnotu jako je nadpis článku.

Author *


Pole Author nesmí být stejné jako pole Title! Mám to tu jako ochranu proti spamu. Roboti to nevyplní dobře :-)

Body *


Type number two as digit *


Semhle vyplňte číslici dvě. Předchozí antispemové pole nefunguje úplně dokonale, zdá se, že jsou i spamery, které pochopily, že je občas potřeba vyplnit autora :-)

Email


Emailová adresa, pokud na ni chcete ode mě dostat odpověď. Nikdo jiný než já vaši emailovou adresu neuvidí.

Attachments