csv PowerShell文件属性列表

41zrol4v  于 2023-05-11  发布在  Shell
关注(0)|答案(2)|浏览(79)

我尝试在Win 2008中使用PowerShell收集一些文件属性。为此,我创建了以下脚本。

# BASIC PARAMETER IF NOT SET
param(
    $REGEX='.*'
    )

# CURRENT DATE FROM 00H
$DATAATUAL = Get-Date -Hour 0 -Minute 0 -Second 0 -Day 1 # DAY 1 FOR TESTING ONLY

# APPLICATION'S FILE PATH
$PATH = "C:\FTP\import\"

# FILE LIST WITH SELECTED FILES FROM REGULAR EXPRESSION
$FILELIST = Get-ChildItem -Path $PATH | Where-Object { ($_.LastWriteTime -ge $DATAATUAL) -and ($_.Name -cmatch "$REGEX") } | Select-Object -ExpandProperty Name

# OUTPUT IN A SORT OF CSV FORMAT
if ($FILELIST -ne $null) {

    Write-Host "name;suffix;fileprocstart;filesize;filewrite"

    ForEach ($FILE in $FILELIST) {
        
        # FILE NAME PREFIX AND SUFFIX
        $FILENAME = Select-String -InputObject $FILE -CaseSensitive -Pattern "(^\d+)_($REGEX)"
        
        # FILE TIMESTAMP CONVERSION TO EPOCH UTC-0
        $FILEPROCSTART = $FILENAME.Matches.Groups[1].value
            $FILEPROCSTART = [datetime]::ParseExact($FILEPROCSTART,"yyyyMMddHHmmss",$null) | Get-Date -UFormat "%s"
            $FILEPROCSTART = $($FILEPROCSTART -as [long]) + 10800  # TIMEZONE CORRECTION - ADDED 3H TO BECOME UTC-0
                        
        $FILESUFFIX = $FILENAME.Matches.Groups[2].value
        
        # FILE SIZE AND WRITE TIME
        $FILESIZE = Get-ChildItem -Path $PATH -Filter $FILE | Select-Object -ExpandProperty Length
        $FILEWRITE = Get-ChildItem -Path $PATH -Filter $FILE | Select-Object -ExpandProperty LastWriteTime | Get-Date -UFormat "%s"
        
        # OUTPUT
        Write-Host "$FILENAME;$FILESUFFIX;$FILEPROCSTART;$FILESIZE;$FILEWRITE"
    }
}

# NO FILES FOUND
Else {
    Write-Host "Empty"
}

我可以这样开始:
script.ps1 -REGEX 'pattern'
它会产生如下列表:

name;suffix;fileprocstart;filesize;filewrite
20220709101112_cacs1_v83.txt;cacs1_v83.txt;1657361472;5;1657397022,47321
20220709101112_cacs1_v83.txt.log;cacs1_v83.txt.log;1657361472;5;1657397041,83271
20220709101112_cacs2_v83.txt;cacs2_v83.txt;1657361472;5;1657397039,70775
20220709101112_cacs3_v83.txt.log;cacs3_v83.txt.log;1657361472;5;1657397038,03647
20220709101112_cakauto4.txt;cakauto4.txt;1657361472;5;1657397037,48906
20220709111112_coord_multicanal.txt.log;coord_multicanal.txt.log;1657365072;5;1657398468,95865

所有文件都是每天生成的,格式如下:

20220709101112_cacs1_v83.txt
20220709101112_cacs1_v83.txt.log
20220709101112_cacs2_v83.txt
20220709101112_cacs3_v83.txt.log
20220709101112_cakauto4.txt
20220709101112_coord_multicanal.txt.log

基本上,脚本输出文件名、文件后缀(无时间戳)、文件时间戳(unix)、文件大小和上次写入时间(unix),所有这些都是以CSV格式输出的。它旨在由另一个系统启动以收集这些属性。
这是一种工作,但我忍不住想一定有一个更好的方法来做到这一点。
有没有考虑过如何改进它?

ddrv8njm

ddrv8njm1#

我不确定我是否理解对了,但如果我理解对了:
基本上,脚本输出文件名、文件后缀、文件名时间戳、文件大小和Last Write时间,所有这些都是CSV格式。它旨在由另一个系统启动以收集这些属性。
这应该是你需要开始的所有内容:

$ComputerName = 'RemoteW2K8Computer'
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
    Get-ChildItem -Path 'C:\FTP\import' |
        Select-Object -Property BaseName,Extension,Length,LastWriteTime,
            @{Name = 'FileNameTimeStamp'; Expression = {($_.BaseName -split '_')[0]}}
}
rwqw0loc

rwqw0loc2#

使用@Olaf伟大的技巧,我已经这样重写了脚本。

param($REGEX='.*')
$DATAATUAL = Get-Date -Hour 0 -Minute 0 -Second 0 -Day 1 # DAY 1 FOR TESTING ONLY
$PATH = "C:\FTP\import"
$TZ = [TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time")

$FILELIST = Get-ChildItem -Path $PATH |
    Where-Object { ($_.LastWriteTime -ge $DATAATUAL) -and ($_.Name -cmatch "$REGEX") } |
        Select-Object -Property Name,Length,
            @{Name = 'Suffix'; Expression = { ($_.Name -split '_',2)[1] } },
            @{Name = 'ProcStart'; Expression = {
                $PROCSTART = ($_.Name -split '_')[0]; 
                $PROCSTART = [datetime]::ParseExact($PROCSTART,"yyyyMMddHHmmss",$null);
                [TimeZoneInfo]::ConvertTimeToUtc($PROCSTART, $TZ) | Get-Date -UFormat "%s";
                } },
            @{Name = 'FileWrite' ; Expression = {
                $WRITETIME = $_.LastWriteTime;
                [TimeZoneInfo]::ConvertTimeToUtc($WRITETIME) | Get-Date -UFormat "%s";
                } }

if ($FILELIST -ne $null) {
    Write-Host "name;suffix;procstart;filesize;filewrite"
    # $FILELIST | ConvertTo-Csv -Delimiter ';' -NoTypeInformation

    ForEach ($FILE in $FILELIST) {
        $FILENAME = $FILE.Name
        $FILESUFFIX = $FILE.Suffix
        $FILESIZE = $FILE.Length
        $FILEPROCSTART = $FILE.ProcStart
        $FILEWRITE = $FILE.FileWrite
        
        Write-Host "$FILENAME;$FILESUFFIX;$FILESIZE;$FILEPROCSTART;$FILEWRITE"
    }
} 
Else {
    Write-Host "Empty"
}

如前所述,输出是CSV格式的。

name;suffix;procstart;filesize;filewrite
20220709101112_cacs1_v83.txt;cacs1_v83.txt;5;1657361472;1657397022,47321
20220709101112_cacs1_v83.txt.log;cacs1_v83.txt.log;5;1657361472;1657397041,83271

如果我使用ConvertTo-Csv(更简单)而不是ForEach,输出也将是CSV。但是,它在其他地方放置了引号,这些引号会扰乱其他到JSON的转换(也许我可以稍后改进)。

# $FILELIST | ConvertTo-Csv -Delimiter ';' -NoTypeInformation
"Name";"Length";"Suffix";"ProcStart";"FileWrite"
"20220709101112_cacs1_v83.txt";"5";"cacs1_v83.txt";"1657361472";"1657397022,47321"
"20220709101112_cacs1_v83.txt.log";"5";"cacs1_v83.txt.log";"1657361472";"1657397041,83271"

另一个系统将其转换为这个(我不能在Win 2008中使用ConvertTo-Json:-/):

{
  "\"Name\"": "\"20220709101112_cacs1_v83.txt\"",
  "\"Length\"": "\"5\"",
  "\"Suffix\"": "\"cacs1_v83.txt\"",
  "\"ProcStart\"": "\"1657361472\"",
  "\"FileWrite\"": "\"1657397022,47321\""
}

因此,我发现用ForEach写值可以得到更清晰的输出。
此外,为了好玩,使用Measure-Command进行测量,我发现新脚本的速度更快。使用小型数据集时,上一个脚本大约需要24毫秒才能完成。现在,使用相同的数据集,新的需要大约13毫秒。
总而言之,一个小的,但很好的改进,我猜。
为@Olaf指出一个更好的剧本和他的耐心干杯。谢谢大家。

相关问题