рекурсивная проверка / копирование файлов, не достигающих более глубокого уровня каталога, чтобы сначала проверить атрибуты файла - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь скопировать файлы для резервного копирования. Я знаю, что некоторые файлы не будут скопированы без сообщения об ошибке из-за атрибутов. Я хочу регистрировать эти файлы, а не пытаться их копировать, так как для этого требуется вечность. Кроме того, мы хотим вернуться и исправить / войти или удалить любые файлы, которые не копируются, как только мы их найдем.

К сожалению, я пытаюсь найти более глубокий подкаталог, и пытаюсь скопировать этот каталог, и он копирует все файлы в каталоге, когда у некоторых есть атрибут, который я бы не хотел копировать. Пример:

\ drive \ folder \ Forms \ C Forms \ и он говорит, что это хороший атрибут "16"

но в этом каталоге есть файл, который копия пытается скопировать в мой каталог dest, и я вижу, что в нем есть атрибуты:

file.pdf Архив, SparseFile, ReparsePoint, Автономно.

Я нашел это с помощью cd для dir и с помощью этой команды:

dir | выберите Имя, Атрибуты

Я смотрел на рекурс, не затрагивающий все уровни , но я думаю, что рекурс не затрагивает все уровни, а в том, что он копирует каталоги более высокого уровня, и файлы тоже идут вместе, без проверки атрибутов первый.

Я искал как проверить, есть ли путь к каталогу или файлу для идей, но когда я попытался добавить проверку вокруг копии, он пропускал добавление каталога над файлом в нем:

if(!((Get-Item $_) -is [System.IO.DirectoryInfo])) #true gives dir, false gives file, only handle if file

Это мой код для функции копирования (я пробовал исключить, но это не сработало):

    function CopyFileToFolderUNC($SourcePath, $DestinationPath, $exclude){
       if(-Not (Test-Path $SourcePath )) #-PathType Container
       {
          $global:ErrorStrings.Add("Exception: No such path, $SourcePath;;  ")
          write-output  "++ Error: An error occured during copy operation. No such path, $SourcePath ++"
       }
       #$tempFileName = [System.IO.Path]::GetFileName($SourcePath)
       #$tempDestFileNamePath = "$DestinationPath\$tempFileName"
       Get-ChildItem -Path $SourcePath  -Recurse  -Depth 2| ForEach {$_} { #added file removed force -File , $SourcePath\*, $SourcePath\*\* -Depth 3
          #test if maybe we are dealing with an off-line file here
          #or use the enum name 'Offline'
          # or use the numeric value: 4096
          #$oldAttribs = $null
          $attr = $_.Attributes.value__
          write-output  "++ $_ $attr ++"
          if (($_.Attributes -eq [System.IO.FileAttributes]::Offline) -or ($_.Attributes.value__ -eq "4096")) {
             $_.Attributes=[System.IO.FileAttributes]::Normal
             #$oldAttribs = $_.Attributes
             #make it a 'normal' file with only the Archive bit set
             #$_.Attributes = [System.IO.FileAttributes]::Archive
             #log that the file was an issue and copy the other ones
             $global:ErrorStrings.Add("Found offline file in backup dir, $_. Logging info and not copying this file. Offline. Please investigate.;;  ")
             write-output  "++ Error: An error occured during copy operation. No such path or file, Offline $_ ++"
          } #if
          elseif(($_.Attributes -eq [System.IO.Fileattributes]::Archive) -or ($_.Attributes.value__ -eq "32")) {
             $global:ErrorStrings.Add("Found archive file in backup dir, $_. Logging info and not copying this file. Archive. Please investigate.;;  ")
             write-output  "++ Error: An error occured during copy operation. No such path or file, Archive $_ ++"
          } #elseif
          elseif(($_.Attributes -eq [System.IO.Fileattributes]::SparseFile) -or ($_.Attributes.value__ -eq "512")) {
             $global:ErrorStrings.Add("Found sparse file in backup dir, $_. Logging info and not copying this file. SparseFile. Please investigate.;;  ")
             write-output  "++ Error: An error occured during copy operation. No such path or file, SparseFile $_ ++"
          } #elseif
          elseif(($_.Attributes -eq [System.IO.Fileattributes]::ReparsePoint) -or ($_.Attributes.value__ -eq "1024")) {
             $global:ErrorStrings.Add("Found reparse point file in backup dir, $_. Logging info and not copying this file. ReparsePoint. Please investigate.;;  ")
             write-output  "++ Error: An error occured during copy operation. No such path or file, ReparsePoint $_ ++"
          } #elseif
          elseif( ($_.Attributes.value__ -eq "5664")) { #($_.Attributes -eq [System.IO.Fileattributes]::ReparsePoint) -or
             $global:ErrorStrings.Add("Found reparse point file in backup dir, $_. Logging info and not copying this file. ReparsePoint. Please investigate.;;  ")
             write-output  "++ Error: An error occured during copy operation. No such path or file, ReparsePoint $_ ++"
          } #elseif
          else {

             #the file is not or no longer off-line, so proceed with the copy
             #only if it's a file and not a dir
             #if(!((Get-Item $_) -is [System.IO.DirectoryInfo])) #true gives dir, false gives file.  We want to copy the files.
             #{
                write-output "Copying $_"
                $_ | Copy-Item -Destination $DestinationPath -Force -Recurse -ErrorVariable errors
                foreach($error in $errors)
                {
                  if ($error.Exception -ne $null)
                  {
                      $global:ErrorStrings.Add("Exception: $($error.Exception);;  ")
                      write-output  "++ Error: An error occured during copy operation. Exception: $($error.Exception) ++"
                  }
                  write-output  "Error: An error occured during copy operation. Exception: $($error.Exception)"
                }
             #}
             #else
             #{
             #   write-output "this is a dir"
             #}
          } #else
    } #Get-ChildItem
 } #function

Вот откуда он вызывается:

$tempSource = @("\\drive\Svcs\Cr\C FORMS\",...) 
$ToLocation = @("E:\DisasterBackup\toLoc\All Forms \",...)   
$excludeNonSharepoint = @("\\drive\Svcs\Cred\op\zOLD_NOT USED_keep for now"...)

#non-sharepoint ones first
for($i=0; $i -lt ($tempSource.Length); $i++) {
   CopyFileToFolderUNC $tempSource[$i] $ToLocation[$i] $excludeNonSharepoint
}

По запросу, пример Минимальный, Полный и Проверяемый:

Таким образом, для этого каталога / файлов / атрибутов после проверки копия будет завершена следующим образом:

source From Location:
\\drive\folder\Forms attrib = normal/16 
\\drive\folder\Forms\a.txt attrib = normal/16 will copy
\\drive\folder\Forms\b.txt attrib = not normal/32/512/1024/etc will not copy  but log
\\drive\folder\Forms\C Forms = normal/16 
\\drive\folder\Forms\C Forms\c.txt  attrib = normal/16 will copy
\\drive\folder\Forms\C Forms\d.txt attrib = not normal/32/512/1024/etc will not copy but log/write-output
\\drive\folder\Forms\C Forms\e.txt attrib = not normal/32/512/1024/etc will not copy but log/write-output
\\drive\folder\Forms\C Forms\f.txt attrib = not normal/32/512/1024/etc will not copy but log/write-output
\\drive\folder\Forms\C Forms\subdir attribute = normal/16 
\\drive\folder\Forms\C Forms\subdir\g.txt  attribute = normal/16 
\\drive\folder\Forms\C Forms\subdir\h.txt attribute = not normal/32/512/1024/etc will not copy but log/write-output

final To Location:
E:\DisasterBackup\toLoc\All Forms\a.txt
E:\DisasterBackup\toLoc\All Forms\C Forms
E:\DisasterBackup\toLoc\All Forms\C Forms
E:\DisasterBackup\toLoc\All Forms\C Forms\c.txt
E:\DisasterBackup\toLoc\All Forms\C Forms\subdir\
E:\DisasterBackup\toLoc\All Forms\C Forms\subdir\g.txt  

output string at the end of the script will be something like:
"Could not copy \\drive\folder\Forms\C Forms\d.txt attrib archive
Could not copy \\drive\folder\Forms\C Forms\e.txt attrib sparse
Could not copy \\drive\folder\Forms\C Forms\f.txt attrib reparse
Could not copy \\drive\folder\Forms\C Forms\subdir\h.txt attrib offline"
...