Удаление элементов из одного CSV на основе элементов в другом файле CSV - PullRequest
1 голос
/ 17 марта 2012

У меня есть скрипт, который будет генерировать файл CSV. Цель сценария - проверить, отсутствует ли определенный файл. Например, допустим, у меня есть следующие файлы:

1.jpg
2.jpg
3.jpg
4.jpg

1.gif
3.gif

2.txt
3.txt

Как только скрипт будет запущен, он сгенерирует отчет, чтобы я мог визуально увидеть, какой файл отсутствует. Отчет выглядит так:

JPG Files   GIF Files   TXT Files
1.jpg       1.gif   
2.jpg                   2.txt
3.jpg       3.gif       3.txt

Как видите, мне не хватает 1.txt и 2.gif.

Здесь моя проблема ...

Теперь у меня есть ВТОРОЙ файл CSV, в котором есть список файлов, которые ДОЛЖНЫ храниться в ПЕРВОМ CSV. Все, что НЕ находится во ВТОРОМ файле CSV, теперь должно быть удалено из моего FIRST CSV. Например:

Мой ПЕРВЫЙ CSV содержит:

1.jpg
2.jpg
3.jpg

1.gif
3.gif

2.txt
3.txt

ВТОРОЙ CSV говорит, что должны остаться следующие файлы:

1.jpg
3.jpg

1.gif

2.txt

Следовательно, все, что не отображается в файле SECOND CSV, необходимо удалить из FIRST CSV, сохранив тот же формат, что означает, что если 1.jpg отсутствует (он все еще указан в файле SECOND CSV, но существует в папке C: \ JPG) в ПЕРВОМ CSV должно быть пустое пространство.

Надеюсь, это имеет смысл. Пожалуйста, спросите меня, если у вас есть какие-либо вопросы или вам нужны разъяснения.

Ниже приведен фрагмент кода из моего скрипта, который генерирует FIRST CSV:

# Get dirs
$dirJPG = "C:\JPG"
$dirGIF = "C:\GIF"
$dirTXT = "C:\TXT"
$files = @()
$files += Get-ChildItem -Path $dirBGR -Filter "*.jpg"
$files += Get-ChildItem -Path $dirMI -Filter "*.gif"
$files += Get-ChildItem -Path $dirW3F -Filter "*.txt"


# Write a datetime stamped CSV file
$datetime = Get-Date -Format "MM_dd_yyyy_hhmm"
$files | Sort-Object -Property { $_.Name } | Group-Object -Property { 
[System.IO.Path]::GetFileNameWithoutExtension($_.Name) } | % {
            New-Object psobject -Property @{
                            "JPG" Files" = $_.Group | ? { $_.Extension -eq ".jpg" } | % { $_.Name }
                            "GIF Files" = $_.Group | ? { $_.Extension -eq ".gif" } | % { $_.Name }
                            "TXT Files" = $_.Group | ? { $_.Extension -eq ".txt" } | % { $_.Name }
            } } | Export-Csv -Path "$datetime.csv" -NoTypeInformation

Заранее спасибо за вашу помощь! : D

Ответы [ 3 ]

1 голос
/ 17 марта 2012

Можно использовать массивы, но, вероятно, будет более эффективно использовать хеш-таблицы.Вы можете проверить итерацию (foreach) по первым элементам CSV и проверить, находятся ли файлы в CSV1, а не в CSV2:

# Get the files by directory for each file type
function Get-FilesByType() {
    param ([hashtable]$filters)

    $result = @{}
    foreach ($filter in $filters.Keys) {
        $path = $filters[$filter]
        Get-ChildItem -Path $path -Filter $filter | % {
            $result.Add($_.Name, $_)
        }
    }
    return $result
}

# Assume CSV1 hashtable already exists and is loaded

# Get the hashtable of files for CSV2
$csv2 = Get-FilesByType @{"*.jpg"="C:\JPG"; "*.gif"="C:\GIF"; "*.txt"="C:\TXT" }

# Remove items from CSV1 that do not exist in CSV2
# NOTE: You cannot remove items from the hashtable while
# iterating through the collection, so use a copy of the
# keys to iterate.
$keys = @()
$keys += $csv1.Keys
$keys | % {
    if ( ! $csv2.ContainsKey($_) ) {
        Write-Host "Removing $_"
        $csv1.Remove($_)
    }
}

# Write a datetime stamped CSV file
$datetime = Get-Date -Format "MM_dd_yyyy_hhmm"
$csv1.Values | Sort-Object -Property { $_.Name } | Group-Object -Property {
    [System.IO.Path]::GetFileNameWithoutExtension($_.Name)
} | % {
    New-Object psobject -Property @{
        "JPG Files" = $_.Group | ? { $_.Extension -eq ".jpg" } | % { $_.Name }
        "GIF Files" = $_.Group | ? { $_.Extension -eq ".gif" } | % { $_.Name }
        "TXT Files" = $_.Group | ? { $_.Extension -eq ".txt" } | % { $_.Name }
    }
} | Export-Csv -Path "$datetime.csv" -NoTypeInformation
0 голосов
/ 20 марта 2012

Нашел, в чём моя проблема ... Я звонил в файлы, которые нужно было удалить, а затем удалял их. Мне просто нужно было добавить условие not:

$keys = @()
$keys += $currentFiles.Keys
$keys | % {
    if (! $filesToKeep.ContainsKey($_)) {
        Write-Host "Removing $_"
        $currentFiles.Remove($_)
    }
}
0 голосов
/ 17 марта 2012

Не используйте массив - используйте Hashtable, как сказал Райан.Массив не является хорошим выбором, если вы хотите удалить из него элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...