Powershell - найти, скопировать, перечислить отсутствующие файлы - PullRequest
0 голосов
/ 06 марта 2020

Я использую PowerShell, чтобы помочь мне найти список файлов из списка, созданного в CVS. Мне нужно, чтобы искать через папку и ее подпапку. скопируйте файлы, перечисленные в CVS, и выведите файлы, которые не найдены в папке, в файл log.txt.

Я нашел этот скрипт в списке ниже, но я не знаю, как заставить его выводить список отсутствующих файлов в файл log.txt.

$source      = "C:\Folder-A"
$destination = "C:\Folder-B"

$file_list = Get-Content "C:\Book1.csv" 

foreach ($file in $file_list){
    foreach($dir in (Get-ChildItem $source -Recurse)){
        if($file -eq $dir.name){
            if(-not(test-path "$destination\$file")){
                Copy-Item $dir.fullname -Destination $destination
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 06 марта 2020

Предполагая, что нам нужны все файлы в месте назначения, когда мы закончим, и список файлов - это просто список имен файлов без пути, мы просто извлекаем существующее, используя рекурсивный get-childitem, затем копируем все файлы в место назначения, используя -force. -confirm: $ false и изменить существующий список с нашим списком файлов. Вы столкнетесь с ошибками, потому что у вас нет информации о пути, и вы рискуете получить дубликаты из-за вложенных папок и -recursive. Вместо этого вытащите все в режиме реального времени, точно так же, как это сделали бы robocopy или rsyn c, и сработайте и сделайте запись:

$source = "C:\Folder-A"
$destination = "C:\Folder-B"
$logfile="C:\logfile.csv"
$files=@()
$existinglist=(Get-ChildItem $destination -Recurse -erroraction silentlycontinue)
$file_list = (Get-ChildItem $source -Recurse -erroraction silentlycontinue)

foreach ($file in $file_list){
    if ($existinglist.Name -contains $file.name){
        $filedestination=$existinglist |?{$_.name -like $file.name}
        Copy-Item $file.fullname -Destination $filedestination.fullname -force -confirm:$false
        $tempitem1=new-object pscustomobject
        add-member -InputObject $tempitem1 -NotePropertyName "filename" -NotePropertyValue $file
        add-member -inputobject $tempitem1 -NotePropertyName "existed" -NotePropertyValue $true
        $files+=$tempitem1
    }else{
        Copy-Item $file.fullname -Destination $destination -force -confirm:$false
        $tempitem1=New-Object pscustomobject
        add-member -InputObject $tempitem1 -NotePropertyName "filename" -NotePropertyValue $file
        add-member -InputObject $tempitem1 -NotePropertyName "existed" -NotePropertyValue $false
        $files+=$tempitem1
}

$files |export-csv -path $logfile -NoTypeInformation

Я предполагаю, что это для образовательных целей, поскольку вы новичок в powershell и любопытно, что здорово, и почему у нас есть ответ и объяснение с кодом. В производстве мы должны использовать robocopy https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy или * nix we go для rsyn c https://wiki.archlinux.org/index.php/Rsync. Надеюсь, это поможет!

0 голосов
/ 06 марта 2020

В вашем коде есть некоторые проблемы, связанные с тем, чего вы пытаетесь достичь:

  1. Ваша переменная '$ dir' фактически будет файлами и каталогами, если в древовидной структуре нет ничего, кроме каталоги (без файлов)
  2. Вы выполняете копирование намного чаще, чем нужно, из-за двойного l oop и выполняете копирование при каждом условном сбое (если ($ file -eq $ dir .name))

test

$source      = "C:\Folder-A"
$destination = "C:\Folder-B"

# will be an array of values, from your code, appears to be an array of file name values alone
$file_list = Get-Content "C:\Book1.csv" 

# Return the FileSystemObjects (Files AND Directories), recursively
$FSOs = (Get-ChildItem $source -Recurse)

# Iterate through each entry in the desired list
foreach ($file in $file_list){

    # Create a string-based array of only the recurive files+directory names and see if our desired name-value is contained in it
    if(($FSOs | Select -ExpandProperty Name) -contains $file){

        # Check to see if it exists in the destination location and if not, copy it
        if(-not(test-path "$destination\$file")){
            Copy-Item $dir.fullname -Destination $destination
        }
    } else {  # For the values from the text-file that were not found in the directory structure, append them to a log file
        $file | Out-File 'NotFoundInDirectory.log' -Append
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...