Показать полную графическую версию : Сравнение файла с оригиналом, создание отчета
tarasov.evgeny
26-09-2012, 17:25
Добрый день,
Есть папка, в которую люди выкладывают файлы.
Необходимо проверить все ли люди выложи файлы, если нет - записть в отчет - забыли.txt
Затем все файлы проверяются на соответствие определенным атрибутам(все атрибуты закодированы в имени файла), если всё верно - файлы перемещаются в папку с именем сегодняшней даты
Если атрибуты файлов не верные - запись в отчет - неверно.txt
Как планируется проверять все ли люди выложили файлы в папку.
Есть файл - сотрудники.txt вот такого вида:
33-1:Отдел1:Иванов:555
22:Отдел2:Петров:333
Файлы, которые выкладывают люди имеет имя:sr_33-1_20120926.rar.enc
Надо создать проверку одного массива данных
get-content .\сотрудники.txt -replace ":.*",""
другому массиву - массиву файлов:
$files = (get-childitem).Basename
В случае если совпадение есть - то выполнять проверку дальше
В случае если совпадения нет формировать отчет забыли.txt или ошибки.txt
Отчеты такого вида:
33-1 Отдел1 Иванов 555 Ошибка
22 Отдел2 Петров 333 Ошибка
Под ошибкой понимается тип ошибки - отсутствие атрибута
Для отчета забыли отчет:
33-1 Отдел1 Иванов 555
22 Отдел2 Петров 333
Создал распихивание файлов по папкам с датой в папки - правильные и не правильные.
Не могу создать отчеты, потому что не понятно как сравнить два массива.
Делаю так.
cls
$BASE = Get-Content сотрудники.txt
$BASEName = $BASE -replace ":.*",""
cd y:\TableReports
ForEach ($a in Get-ChildItem)
{
$b=0
if (($a.BaseName -replace "^S_","" -replace "_.*","") -like $BASEName[$b])
{
'Move-item $a.Basename'
}
else
{
"Write to log-file"
}
$b=$b+1
}
Вот постоянно выдает, что не верно (то есть выполняет команду else)
Хотя одно значение должно совпадать точно
А если просто из строки выполнить
($a[1].BaseName -replace "^S_","" -replace "_.*","") -like $BASEName[$b]
Говорит True - То есть должен был бы выполнить условие до else - или другими словами одно совпадение найдено (правда здесь конкретная проверка - одно значение с другим.
Кстати только что понял, что я ожидал ответ от одиночной команды вида:
33-1 (я ведь написал -like а не -contains)
а он выдает True или False
Такого формата имя:sr_33-1_20120926.rar.enc файл не может быть.
Файл должен быть в кодировке Unicode
$base = Import-Csv сотрудники.txt -Delimiter ":" -Header "O","T",TH","F"
$files = Get-ChildItem D:\ | Where {!$_.PsIsContainer} | Select-Object -Expand FullName
foreach($name in $base)
{
$find = $files -match $name.th
if($find)
{
'Move-item $find'
}
else
{
'Write to log-file'
}}
tarasov.evgeny
27-09-2012, 18:08
Благодарю за помощь.
Теперь не могу скопировать данные.
cls
cd y:\
$base = Import-Csv DATA.txt -Delimiter ":" -Header "N","Отдел","Контактный номер"
$files = Get-ChildItem Y:\TableReports | Where {!$_.PsIsContainer -and $_.Name -match ".enc$"} | Select-Object -Expand FullName
$DayFolder = New-item -Path Y:\week -name "$(Get-Date -uformat '%Y%m%d')" -type directory
$DayFolder2 = New-item -Path Y:\markdelete -name "$(Get-Date -uformat '%Y%m%d')" -type directory
cd Y:\TableReports
foreach($name in $base)
{
$findFile = $files -match $name.N
if($findFile)
{
Write-Host "Файл прислали"
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"
if($findAtr)
{
Write-Host "Атрибуты верны"
Copy-Item -Path $findAtr -Destination $DayFolder.FullName
}
else
{
Write-Host "Атрибуты НЕ верны"
$name.N
Copy-Item -Path $findAtr -Destination $DayFolder2.FullName
}
}
else
{
Write-Host "Файл НЕ прислали"
}
}
В базе DATA.txt содержится список контактов. Начинается с номера. Есть номера вида: 53-1
Вот на них и ругается.
...
Атрибуты НЕ верны
33-1
Copy-Item : Не удается привязать аргумент к параметру "Path", так как он представляет собой пустой массив.
C:\Dropbox\VFTP_подписиЧУЖОЙ.ps1:24 знак:18
+ Copy-Item -Path <<<< $findAtr -Destination $DayFolder2.FullName
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyArrayNotAllowed,Microsoft.PowerShell.Commands.
CopyItemCommand
Файл прислали
...
Я так понимаю, что вот эта конструкция:
$findFile = $files -match $name.N
if($findFile)
{}
else
{}
В случае отрицательного значение (переход в else) в $findfile = ничего не возвращает. Как быть?
1) Зачем в скрипте команды?
cd y:\
cd Y:\TableReports
2) $findAtr = $findFile -match "rar.sig.enc$" -cmatch "S" - Какие тут тестируются атрибуты?
3) Copy-Item -Path $findAtr должно быть Copy-Item -Path $findFile
tarasov.evgeny
28-09-2012, 12:15
1.
cd y:\ так как в команде не было полного пути до файла. указываю диск (исправил)
cd y:\tablereports - не могу объяснить :) - удалил
2. Атрибуты - не в привычном смысле слова. То есть это не атрибуты файловый системы (архивный, скрытый, acl, что там ещё...) - эти атрибуты закодированы в имени файла.
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S" - мне нужны файлы, которые оканчиваются на rar.sig.enc и в имени содержат большую букву S.
3. Исправил работает.
Вот такой отчет получился.
Write-Host "Файл НЕ прислали"
$name | Out-File не_прислали.txt -Append
$report = get-content не_прислали.txt
$encoding = [System.Text.Encoding]::UTF8
$body = $report | Where-Object {$_ -ne "" -and $_ -match "[0-9]"}
Send-MailMessage -encoding $encoding -From ftp@company.ru -To my@company.ru -Subject "Отчет об S-файлах. Не отправили:" -Body $body -SmtpServer mail.company.ru
В результате имеем:
22 Number1Номер 1
22-1 Number1Номер 1
44-1 Number2Номер3 222-333
52 NUMBER5 555
53-1 Number2 22223333444
Не очень хорошо читаемо. Что можете посоветовать? Кроме того, я создаю отчет через создание промежуточного файла. Как можно этого избежать?
На всякий случай весь код:
cls
$base = Import-Csv y:\data.txt -Delimiter ":" -Header "N","Отдел","Контактный номер"
$files = Get-ChildItem y:\TableReports | Where {!$_.PsIsContainer -and $_.Name -match ".enc$"} | Select-Object -Expand FullName
$DayFolder = New-item -Path y:\TableReports\week -name "$(Get-Date -uformat '%Y%m%d')" -type directory
$DayFolder2 = New-item -Path y:\TableReports\markdelete -name "$(Get-Date -uformat '%Y%m%d')" -type directory
foreach($name in $base)
{
$findFile = $files -match $name.N
if($findFile)
{
Write-Host "Файл прислали"
$name.N
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"
if($findAtr)
{
Write-Host "Атрибуты верны"
$name.N
Copy-Item -Path $findFile -Destination $DayFolder.FullName
}
else
{
Write-Host "Атрибуты НЕ верны"
$name.N
Copy-Item -Path $findFile -Destination $DayFolder2.FullName
}
}
else
{
Write-Host "Файл НЕ прислали"
$name | Out-File не_прислали.txt -Append
$report = get-content не_прислали.txt
$encoding = [System.Text.Encoding]::UTF8
$body = $report | Where-Object {$_ -ne "" -and $_ -match "[0-9]"}
Send-MailMessage -encoding $encoding -From vftp@company.ru -To my@company.ru -Subject "Отчет об S-файлах. Не отправили:" -Body $body -SmtpServer mail.company.ru
}
}
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S" - Попробуйте узнать результат выполнения,может отработать только в случае массива,что врятли,для скалярного значения всегда выражение будет FALSE.
Добавить перед foreach переменную notfound:
$notfound = @()
foreach($name in $base)
{
$findFile = $files -match $name.N
if($findFile)
{
Write-Host "Файл прислали $($name.N)"
$name.N
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"
if($findAtr)
{
Write-Host "Атрибуты верны"
$name.N
Copy-Item -Path $findFile -Destination $DayFolder.FullName
}
else
{
Write-Host "Атрибуты НЕ верны"
$name.N
Copy-Item -Path $findFile -Destination $DayFolder2.FullName
}
}
else
{
$notfound += $name
Write-Host "Файл не прислали $($name.N)"
}
}
if($notfound)
{
$body = $notfound | Format-Table -auto | Out-String
Send-MailMessage -encoding ([System.Text.Encoding]::UTF8) -From vftp@company.ru -To my@company.ru -Subject "Отчет об S-файлах. Не отправили:" -Body $body -SmtpServer mail.company.ru
}
tarasov.evgeny
02-10-2012, 16:25
Не сколько видоизменил ТЗ.
Один скрипт будет работать как служба.
Служба:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = 'C:\FTP'
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $false
$watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite -bor [System.IO.NotifyFilters]::FileName
while($TRUE){
$result = $watcher.WaitForChanged([System.IO.WatcherChangeTypes]::All, 1000);
if($result.TimedOut){
continue;
}
C:\Scripts\S-files\S-FilesCheck.ps1
}
В случае обнаружения изменений в папке - скрипт будет пинать второй.
Второй скрипт проверяет:
есть ли папка за сегодняшнее число. Если нет, то создает и проверяет файлы на вшивость.
Если файл нормальный, то копируется в папку - нормальные
Если файл не нормальный. копируется в папку не правильные и пишется сообщение на почту, что файл не верный (отображаются контакты накосячивших)
Второй - проверка файлов:
cls
$Checkfolder = Test-Path -Path "c:\Reports\$(Get-Date -uformat '%Y%m%d')"
if($checkfolder -eq $False)
{
New-item -Path "C:\Reports\" -name "$(Get-Date -uformat '%Y%m%d')" -type directory
$DayOK = New-item -Path "C:\Reports\$(Get-Date -uformat '%Y%m%d')" -name 'OK' -type directory
$DayNoOK = New-item -Path "C:\Reports\$(Get-Date -uformat '%Y%m%d')" -name 'NoOK' -type directory
Write-Host "Create folder DATA, NoOK, OK"
}
$base = Import-Csv C:\Scripts\S-files\data.txt -Delimiter ":" -Header "N","Отдел","Контактное лицо", "Телефон"
$files = Get-ChildItem c:\ftp | Where {!$_.PsIsContainer -and $_.Name -match ".enc$"} | Select-Object -Expand FullName
foreach($name in $base)
{
$findFile = $files -match $name.N
if($findFile)
{
Write-Host "Файл прислали $name.N"
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"
if($findAtr)
{
Write-Host "Атрибуты верны"
# Move-Item -Path $($findFile) -Destination $DayOK.FullName
}
else
{
Write-Host "Атрибуты НЕ верны"
# Copy-Item -Path $($findFile) -Destination $DayNoOK.FullName
}
}
}
Третий скрипт в одно время формирует список тех, кто не прислал файл вообще и отправляет отчет на почту
Второй вообще не отрабатывает. Причем как с @(notfound) так и без неё (я не до конца понял, как это работает).
А то что отрабатывает вообще не понятно как отрабатывает
Скажем по факту два файла. Один нормальный, второй нет.
А скрипт говорит, что:
- все атрибуты верны
- что прислали файл не два человек, а скажем 5
Я уже третий раз спрашиваю про условие "$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"" - ЧТО ЭТО?
tarasov.evgeny
02-10-2012, 16:52
Извиняюсь. Я вроде как ответил.
$findFile = $files -match $name.N
if($findFile)
Это первая проверка - ищем файл. Если нашли, то:
$findAtr = $findFile -match "rar.sig.enc$" -cmatch "S"
весь путь, который нам возвращает вот эта команда
$files = Get-ChildItem c:\ftp | Where {!$_.PsIsContainer -and $_.Name -match ".enc$"} | Select-Object -Expand FullName
Например,
C:\ftp\S_11_20121002.rar.sig.enc
проверяем на содержание - есть ли в строчке - S, rar.sig.enc
$files.GetType().Name - возвращает string.
$findatr - возвращает boolean
Поэтому путь не подставлялся (boolean никак не подставишь), а отчет выдает больше вхождения - потому что files по символам разбирается.
Но как сделать правильно?
Нужно вот это изменить:
"$findAtr = $files -match "rar.sig.enc$" -cmatch "S"
Тогда еще разок(в 6 посте я это описал,но читать конечно же не обязательно):
PS Z:\> "C:\ftp\S_11_20121002.rar.sig.enc" -match "rar.sig.enc$" -cmatch "S"
False
PS Z:\> "C:\ftp\S_11_20121002.rar.sig.enc" -match "rar.sig.enc$"
True
$findAtr = $findFile -match "\\S.+\.rar\.sig\.enc$"
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.