#powershell
#powershell
Вопрос:
У меня есть скрипт powershell, который выполняет инвентаризацию файлового ресурса. Я хочу знать, как добавить идентификатор к каждой строке в csv-файле, а также родительский идентификатор к строке в csv.
Я новичок в Powershell, но разобрался, как заставить скрипт инвентаризации работать. Вот код.
#Set-ExecutionPolicy Unrestricted
$SourcePath = "G:My Drive"
$DestinationCSVPath = "e:G Drive Inventory 20180611.csv" #Destination for Temp CSV File
$CSVColumnOrder = 'Path', 'IsDIR', 'Directory', 'FileCount', 'Parent', 'Name', 'CreationTime', 'LastAccessTime', 'LastWriteTime', 'Extension', 'BaseName', 'B'
#, 'Root', 'IsReadOnly', 'Attributes', 'Owner', 'AccessToString', 'Group' #, #'MD5', #'SHA1' #Order in which columns in CSV Output are ordered
#FOLDERS ONLY
#$SourcePathFileOutput = Get-ChildItem $SourcePath -Recurse | where {$_.PSIsContainer}
#FILES AND FOLDERS
$SourcePathFileOutput = Get-ChildItem $SourcePath -Recurse #| where {$_.PSIsContainer} #Uncomment for folders only
$HashOutput = ForEach ($file in $SourcePathFileOutput) {
Write-Output (New-Object -TypeName PSCustomObject -Property @{
Path = $file.FullName
IsDIR = $file.PSIsContainer
Directory = $File.DirectoryName
FileCount = (GCI $File.FullName -Recurse).Count
Parent = $file.Parent
Name = $File.Name
CreationTime = $File.CreationTime
LastAccessTime = $File.LastAccessTime
LastWriteTime = $File.LastWriteTime
Extension = $File.Extension
BaseName = $File.BaseName
B = $File.Length
#Root = $file.Root
#IsReadOnly = $file.IsReadOnly
#Attributes = $file.Attributes
#Owner = $acl.owner
#AccessToString = $acl.accesstostring
#Group = $acl.group
#MD5 = Get-FileHash $file.FullName -Algorithm MD5 | Select-Object -ExpandProperty Hash
#SHA1 = Get-FileHash $file.FullName -Algorithm SHA1 | Select-Object -ExpandProperty Hash
}) | Select-Object $CSVColumnOrder
}
$HashOutput | Export-Csv -NoTypeInformation -Path $DestinationCSVPath
Я хочу знать, как добавить идентификатор к каждой строке в csv-файле, а также родительский идентификатор к строке в csv.
Комментарии:
1. Я совсем не уверен, что вы имеете в виду под
ID
… Не могли бы вы подробнее остановиться на этом и, возможно, привести пример желаемого результата?2. Присвоение уникального идентификатора каждому результату, а также последующее вычисление родительского элемента. Например C:files, Идентификатор 1, родительский идентификатор 0, C:FilesFolder Идентификатор 2, родительский идентификатор 1 и т.д. По ходу работы генерирует свой список вместе со всеми другими вычислениями.
Ответ №1:
попробуйте что-то вроде этого:
$ID=1
$SourcePath="c:temp"
$SourcePathFileOutput=@()
#for have the parent dir
$SourcePathFileOutput = Get-Item $SourcePath | %{
$ParentPath=if ($_.PSIsContainer){$_.parent.FullName}else{$_.DirectoryName}
Add-Member -InputObject $_ -MemberType NoteProperty -Name "ID" -Value ($ID )
Add-Member -InputObject $_ -MemberType NoteProperty -Name "PARENTPATH" -Value $ParentPath
$_
}
#for have all directory and file
$SourcePathFileOutput = Get-ChildItem $SourcePath -Recurse | %{
$ParentPath=if ($_.PSIsContainer){$_.parent.FullName}else{$_.DirectoryName}
Add-Member -InputObject $_ -MemberType NoteProperty -Name "ID" -Value ($ID )
Add-Member -InputObject $_ -MemberType NoteProperty -Name "PARENTPATH" -Value $ParentPath
$_
}
#List dir for optimise
$DirOutput=$SourcePathFileOutput | where {$_.psiscontainer}
#for output result (add all properties you want)
$list=foreach ($Current in $SourcePathFileOutput)
{
$Result=[pscustomobject]@{
Path = $Current.FullName
PARENTPATH=$Current.PARENTPATH
ISDIR=$Current.psiscontainer
ID=$Current.ID
PARENTID=($DirOutput | where {$_.FullName -eq $Current.PARENTPATH}).ID
}
#Initialise parent root
if ($Result.PARENTID -eq $null) {$Result.PARENTID=0}
#send result on output
$Result
}
$list | Out-GridView
Ответ №2:
Это должно сделать то, что вы хотите:
#Set-ExecutionPolicy Unrestricted
$SourcePath = "G:My Drive"
$DestinationCSVPath = "e:G Drive Inventory 20180611.csv" #Destination for Temp CSV File
$CSVColumnOrder = 'Path', 'IsDIR', 'Directory', 'FileCount', 'Parent', 'Name', 'CreationTime', 'LastAccessTime', 'LastWriteTime', 'Extension', 'BaseName', 'B','ID','ParentID'
#, 'Root', 'IsReadOnly', 'Attributes', 'Owner', 'AccessToString', 'Group' #, #'MD5', #'SHA1' #Order in which columns in CSV Output are ordered
#FOLDERS ONLY
#$SourcePathFileOutput = Get-ChildItem $SourcePath -Recurse | where {$_.PSIsContainer}
#FILES AND FOLDERS
$SourcePathFileOutput = Get-ChildItem $SourcePath -Recurse | Sort-Object Fullname #| where {$_.PSIsContainer} #Uncomment for folders only
$CurrentID = 1
$IDs = [ordered]@{}
$IDs.add(($SourcePathFileOutput[0].fullname | split-path),0)
$HashOutput = ForEach ($file in $SourcePathFileOutput) {
$IDs.add($file.fullname,$CurrentID)
Write-Output (New-Object -TypeName PSCustomObject -Property @{
ID = $CurrentID
ParentID = $IDs.$($file.fullname | split-path)
Path = $file.FullName
IsDIR = $file.PSIsContainer
Directory = $File.DirectoryName
FileCount = (GCI $File.FullName -Recurse).Count
Parent = $file.Parent
Name = $File.Name
CreationTime = $File.CreationTime
LastAccessTime = $File.LastAccessTime
LastWriteTime = $File.LastWriteTime
Extension = $File.Extension
BaseName = $File.BaseName
B = $File.Length
#Root = $file.Root
#IsReadOnly = $file.IsReadOnly
#Attributes = $file.Attributes
#Owner = $acl.owner
#AccessToString = $acl.accesstostring
#Group = $acl.group
#MD5 = Get-FileHash $file.FullName -Algorithm MD5 | Select-Object -ExpandProperty Hash
#SHA1 = Get-FileHash $file.FullName -Algorithm SHA1 | Select-Object -ExpandProperty Hash
}) | Select-Object $CSVColumnOrder
$CurrentID
}
$HashOutput | Export-Csv -NoTypeInformation -Path $DestinationCSVPath
Объяснение:
Я передал по каналу $SourcePathFileOutput
в Sort-Object
, потому что проще всего назначить упорядоченный идентификатор, если объекты отсортированы по их расположению в дереве каталогов.
$CurrentID
начинается с 1, потому что первый элемент в цикле не является корневым родительским элементом. Ваш цикл будет увеличивать эту переменную на 1 ( $CurrentID
) в конце каждой итерации цикла, так что следующему файлу / каталогу будет присвоен новый номер. Поскольку этот код создается $CurrentID
как Int32
тип, у вас возникнут проблемы, если у вас более 2 миллиардов файлов / каталогов. Вам нужно будет инициализировать его как 64-разрядный тип ( $CurrentID = [long]1
). Однако я полагаю, что в хэш-таблице может быть только количество ключей Int32, поэтому при наличии миллиардов файлов потребуется применить другую стратегию.
$IDs
это упорядоченная хэш-таблица, которая отслеживает идентификаторы для всех файлов и каталогов. Каждый ключ в хэш-таблице — это путь к текущему элементу в цикле. Значение является присвоением идентификатора. Это означает, что вы можете получить доступ к идентификатору, используя синтаксис $IDs.path
. После инициализации я добавил первую запись с идентификатором 0, которая представляет корневого родителя.
Внутри цикла я создал ID
свойство, которое просто хранит текущее значение $CurrentID
. Я создал ‘ParentID’, который просматривает родительский каталог внутри $IDs
хэш-таблицы и возвращает значение идентификатора этого ключа.
Я обновил, $CSVColumnOrder
чтобы иметь ID
и ParentID
в качестве столбцов.
Схема идентификаторов могла бы немного отличаться, если бы вы выполнили первоначальную сортировку по-другому. Вам не нужно увеличивать значение на 1. Возможно, у вас есть требование, чтобы идентификаторы каталогов были меньше, чем у файлов, и для этого потребуется больше кода (хотя я не видел этого требования).
Комментарии:
1. Спасибо @AdminOfThings. Я получаю эту ошибку, есть идеи? — Инвентаризация общего доступа к файлам.ps1:20 char: 40 $IDs.add($file. полное имя, $currentId) ~ Отсутствует оператор ‘=’ после ключа в хэш-литерале. В C:UsersUserfileshare inventory.ps1:20 char: 40 $IDs.add($file. полное имя, $currentId) ~ Хэш-литерал был неполным. CategoryInfo: ParserError: (:) [], ParentContainsErrorRecordException FullyQualifiedErrorId : MissingEqualsInHashLiteral
2. @CameronStewart Я обновил код, чтобы устранить эту проблему.