Powershell生成不完整的结果。从join cmdlet中删除显示的逗号

Powershell生成不完整的结果。从join cmdlet中删除显示的逗号,powershell,csv,join,filepath,delimiter,Powershell,Csv,Join,Filepath,Delimiter,我对脚本非常陌生,希望有人能给我一些建议 我亲自创建了一个对项目管理有用的PowerShell脚本。脚本分析文件路径以确定其是否过长,并检查文件名是否少于50个字符。此外,它还确保没有非法字符等。所有结果最初都打印到文本文件中 在PowerShell脚本中,我最初让步骤1、2和3-9生成3个单独的文档。但最终,我决定将所有步骤写入一个文本文件。在最后一步中,将导入文本文件以创建CSV。然后,文件路径按字母顺序排序,并合并返回2个不同结果的任何文件路径。最终,用户将引用此CSV,以便在存档媒体之前

我对脚本非常陌生,希望有人能给我一些建议

我亲自创建了一个对项目管理有用的PowerShell脚本。脚本分析文件路径以确定其是否过长,并检查文件名是否少于50个字符。此外,它还确保没有非法字符等。所有结果最初都打印到文本文件中

在PowerShell脚本中,我最初让步骤1、2和3-9生成3个单独的文档。但最终,我决定将所有步骤写入一个文本文件。在最后一步中,将导入文本文件以创建CSV。然后,文件路径按字母顺序排序,并合并返回2个不同结果的任何文件路径。最终,用户将引用此CSV,以便在存档媒体之前手动更正任何错误

以下是我遇到的问题

  • 从步骤1到9,生成的文本文件不完整。当我检查文本文件时,它会停在写一条路径的中间。我还注意到,在步骤10中创建的CSV也有不完整的结果。

  • 在步骤10中,我使用join cmdlet将结果合并到CSV中。所以,如果一个文件名有两个不同的结果,我想把结果合并成一行。我使用逗号作为分隔符,但当我这样做时,它实际上会在CSV中显示多个逗号。有没有办法防止显示逗号?


  • 您不应该创建这样的临时csv文件,然后再将其转换为csv,这样您就可以直接使用PSCustomObject进行转换并导出csv。
    创建类似csv的临时文件的方式很容易弄乱逗号的数量,从而导致字段不对齐

    此外,我建议不要在CSV标题中使用逗号(或者缩短它们,但这取决于您)

    尝试:

    如您所见,我已更改了一些测试:

    • 已删除regex上的
      (?i)
      -match,因为默认情况下不区分大小写
    • 在正则表达式中将
      -
      移动到前面,如
      [^-a-z0-9.]
      ,因为否则它将被解释为正则表达式范围,而不是减号本身
    • 更改了隐藏文件的测试

    感谢您分享此@Theo。我真的很感谢你的意见。我用您的脚本运行了一个测试,并对它进行了修改,包括
    Export Csv-Path$outputFile-Delimiter','-NoTypeInformation | sort'Path'| Group Object'Path'
    我也在努力工作,但无法准确地找出如何将结果限制在具有值的行。您对此有何想法。@M22613请查看编辑后的答案。自定义对象现在仅在包含任何有趣的属性时才输出。结果现在被捕获到一个变量
    $result
    ,该变量用于创建输出CSV文件,前提是它收集了任何内容。另外,如果您希望csv在路径列上进行排序,请在将其导出到csv之前执行此操作:
    $result |排序对象路径|导出csv-路径$outputFile-NoTypeInformation
    非常感谢您。谢谢你的帮助,也感谢你的教训。@ M2213你可以考虑通过点击旁边的复选图标来接受答案,使之成为“官方”;
    param(
     # $pathToScan Enter the path to scan for file length
     [Parameter(Mandatory=$True,Position=0)]
     [ValidateNotNull()]
     [string]$pathToScan,
     #Character Limit to be set
     [Parameter(Position=1)] 
     #[ValidateNotNull()] 
     [int]$charLimit = 250
    )
    
    
    # File outputs
    #$outputEmptyPath = "C:\temp\EmptyPaths_$(Get-Date -Format yyyyMMdd).csv"
    #$outputCharPath = "C:\temp\SpecialChars_$(Get-Date -Format yyyyMMdd).csv"
    $outputFilePath = "C:\temp\PathLengths_$(Get-Date -Format yyyyMMdd).txt"
    
    # Use this switch to display to screen.  Can ignore this for now.
    $writeToConsoleAsWell = $false   # Writing to the console will be much slower.
    
    # Open a new file stream (nice and fast) and write all the paths and their lengths to it.
    $outputFileDirectory = Split-Path $outputFilePath -Parent
    if (!(Test-Path $outputFileDirectory)) { New-Item $outputFileDirectory -ItemType Directory }
    $streamPath = New-Object System.IO.StreamWriter($outputFilePath, $false)
    #$streamChar = New-Object System.IO.StreamWriter($outputFilePath, $false)
    #$streamEmpty = New-Object System.IO.StreamWriter($outputFilePath, $false)
    
    # STEP 1 - Check for empty paths.
    ((Get-ChildItem -Path $pathToScan -Recurse | Where-Object {$_.PSIsContainer -eq $True}) | Where-Object {$_.GetFiles().Count -eq 0 -and $_.GetDirectories().Count -eq 0}) | ForEach-Object {
          $emptyPaths = $_.FullName
    
          if ($emptyPaths) {
              $streamPath.WriteLine("$emptyPaths , empty folder")
            }
    }
    
    # STEP 2 - Show for long paths. (default=250 characters)
    Get-ChildItem -Path $pathToScan -Recurse | Select-Object -Property BaseName, FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}} | Sort-Object -Property FullNameLength -Descending | ForEach-Object {
        $fileName = $_.BaseName
        $filePath = $_.FullName
        $length = $_.FullNameLength
    
        if ($length -gt $charLimit) {
            $string = "$length : $filePath"
        
            # Write to the Console.
            if ($writeToConsoleAsWell) { Write-Host $string }
    
            #Write to the file.
            $streamPath.WriteLine("$filepath ,, file path too long")
        }
    
        #STEP 3 - Check for special characters. Allowed characters are Alphanumerics, single space, dashes, underscores, periods
        if ($filename -match '[^a-zA-Z0-9 -_.]') {
            $streamPath.WriteLine("$filepath ,,, has special characters")
        }
    
        #STEP 4 - Check for double spaces, dashes, periods and underscores
        if ($filepath -match '\s{2,}|\-{2,}|\.{2,}|_{2,}') {
            $streamPath.WriteLine("$filepath ,,,, has double spaces/dashes/periods/underscores")
        }
        
        #STEP 5 - check for more than 50 characters
        if ($filename -match '[^\\]{51,}\.[a-zA-Z0-9]{2,7}$') {
            $streamPath.WriteLine("$filepath ,,,,, exceeds 50 characters")
       }
    
        #STEP 6 - check for empty space at end of file or folder name
        if ($filename -match '(\s+$)|(\s+\\)|(\s+\.)') {
            $streamPath.WriteLine("$filepath ,,,,,, name has space at end")
       }
       
        #STEP 7 - check for zip and other archived files
        if ($filename -match '(?i)\.zip$|(?i)\.tar.gz$|(?i)\.gz$|(?i)__MACOSX$') {
            $streamPath.WriteLine("$filepath ,,,,,,, unzip files before archiving")
       }
          
        #step 8 - check for cache and render files
        if ($filename -match '(?i)\.cfa$|(?i)\.pek$|(?i)\.xmp$') {
            $streamPath.WriteLine("$filepath ,,,,,,,, delete cache and render files")
       }
    
        #step 9 - check for Windows hidden files
        if ($filename -match '(?i)\._|thumbs.db') {
            $streamPath.WriteLine("$filepath ,,,,,,,,, delete hidden files")
       }
    } 
        Start-Sleep -Seconds 30
    
    #step 10 - Merge and sort results
    Import-Csv -Path "C:\temp\PathLengths_$(Get-Date -Format yyyyMMdd).txt" -Header 'Path', 'Empty Folder', 'Long File Path', 'Special Characters', 'Double Spaces, Dashes, Periods and Underscores', 'Exceeds 50 Characters', 'Name Has Space at End', 'Zip File', 'Cache and Render Files', 'Windows Hidden Files' | sort 'Path' | Group-Object 'Path' | ForEach-Object {
        [PsCustomObject]@{
            'Path' = $_.Name
            'Empty Folder' = $_.Group.'Empty Folder' -join ',' 
            'Long File Path' = $_.Group.'XMP File' -join ',,'
            'Special Characters' = $_.Group.'Special Characters' -join ',,,'
            'Double Spaces, Dashes, Periods and Underscores' = $_.Group.'Double Spaces, Dashes, Periods and Underscores' -join ',,,,'
            'Exceeds 50 Characters' = $_.Group.'Exceeds 50 Characters' -join ',,,,,'
            'Name Has Space at End' = $_.Group.'Name Has Space at End' -join ',,,,,,'
            'Zip File' = $_.Group.'Zip File' -join ',,,,,,,'
            'Cache and Render Files' = $_.Group.'Cache and Render Files' -join ',,,,,,,,'
            'Windows Hidden Files' = $_.Group.'Windows Hidden Files' -join ',,,,,,,,,'        
        }
    } | Export-Csv "C:\temp\PathLengths_$(Get-Date -Format yyyyMMdd)-SORTED_FINAL.csv" -Delimiter ',' -NoTypeInformation
    
    param(
     # $pathToScan Enter the path to scan for file length
     [Parameter(Mandatory = $true, Position = 0)]
     [ValidateScript({ Test-Path -Path $_ -PathType Container })]
     [string]$pathToScan,
    
     #Character Limit to be set
     [int]$charLimit = 250
    )
    
    # File output
    $outputFile = "C:\temp\PathLengths_$(Get-Date -Format yyyyMMdd).csv"
    
    # collect custom objects
    $result = Get-ChildItem -Path $pathToScan -Recurse -Force | ForEach-Object {
        # create the output object.
        $obj = [PsCustomObject]@{
            'Path'                                     = $_.FullName
            'ObjectType'                               = if ($_.PSIsContainer) {'Folder'} else {'File'}
            'Empty Folder'                             = $null
            'Long File Path'                           = $null
            'Special Characters'                       = $null
            'Double Spaces_Dashes_Periods_Underscores' = $null
            'Exceeds 50 Characters'                    = $null
            'Name Has Space at End'                    = $null
            'Zip File'                                 = $null
            'Cache and Render Files'                   = $null
            'Windows Hidden Files'                     = $null
        }
        # STEP 1 - Check for empty paths.
        if ($_.PSIsContainer -and $_.GetFileSystemInfos().Count -eq 0) { $obj.'Empty Folder' = 'empty folder' }
    
        # STEP 2 - Show for long paths. (default=250 characters)
        if ($_.FullName.Length -gt $charLimit) { $obj.'Long File Path' = 'path too long' }
    
        #STEP 3 - Check for special characters. Allowed characters are Alphanumerics, single space, dashes, underscores, periods
        if ($_.BaseName -match '[^-a-z0-9 _.]') { $obj.'Special Characters' = 'has special characters' }
    
        #STEP 4 - Check for double spaces, dashes, periods and underscores
        if ($_.BaseName -match '[-\s._]{2,}') { $obj.'Double Spaces_Dashes_Periods_Underscores' = 'has double spaces/dashes/periods/underscores' }
    
        #STEP 5 - check for more than 50 characters
        # This is a weird check.. Why not simply if ($_.Name.Length -gt 50) ???
        if ($_.Name -match '[^\\]{51,}\.[a-z0-9]{2,7}$') { $obj.'Exceeds 50 Characters' = 'exceeds 50 characters' }
    
        #STEP 6 - check for empty space at end of file or folder name
        if ($_.Name -match '\s$') { $obj.'Name Has Space at End' = 'name ends in whitespace' }
        
        # these are for files only:
        if (!$_.PSIsContainer) {
            #STEP 7 - check for zip and other archived files
            if ($_.Name -match '\.zip$|\.tar|\.gz$|__MACOSX$') { $obj.'Zip File' = 'unzip files before archiving' }
      
            #STEP 8 - check for cache and render files
            if ('.cfa', '.pek', '.xmp' -contains $_.Extension) { $obj.'Cache and Render Files' = 'delete cache and render files' }
    
            #STEP 9 - check for Windows hidden files
            if ($_.Attributes -band [System.IO.FileAttributes]::Hidden) { $obj.'Windows Hidden Files' = 'delete hidden files' }
        }
    
        # output the object, only if there is some value of interest
        # (the first two properties 'Path' and 'ObjectType' are general info, so we disregard those here)
        if (($obj.PsObject.Properties | Select-Object -Skip 2).Value -join '' -ne '') {
            $obj
        }
    }
    
    if ($result) { $result | Export-Csv -Path $outputFile -NoTypeInformation }