简体   繁体   中英

Powershell, Loop through CSV files and search for a string in a row, then Export

I have a directory on a server called 'servername'. In that directory, I have subdirectories whose name is a date. In those date directories, I have about 150 .csv file audit logs. I have a partially working script that starts from inside the date directory, enumerates and loops through the .csv's and searches for a string in a column. Im trying to get it to export the row for each match then go on to the next file.

$files = Get-ChildItem '\\servername\volume\dir1\audit\serverbeingaudited\20180525'

ForEach ($file in $files) {
    $Result = If (import-csv $file.FullName | Where {$_.'path/from' -like "*01May18.xlsx*"})
    {
    $result | Export-CSV -Path c:\temp\output.csv -Append}
    }

What I am doing is searching the 'path\\from' column for a string - like a file name. The column contains data that is always some form of \\folder\\folder\\folder\\filename.xls. I am searching for a specific filename and for all instances of that file name in that column in that file.

My issue is getting that row exported - export.csv is always empty. Id also like to start a directory 'up' and go through each date directory, parse, export, then go on to the next directory and files.

If I break it down to just one file and get it out of the IF it seems to give me a result so I think im getting something wrong in the IF or For-each but apparently thats above my paygrade - cant figure it out....

Thanks in advance for any assistance, RichardX

The issue is your If block, when you say $Result = If () {$Result | ...} $Result = If () {$Result | ...} you are saying that the new $Result is equal what's returned from the if statement. Since $Result hasn't been defined yet, this is $Result = If () {$null | ...} $Result = If () {$null | ...} which is why you are getting a blank line.

The If block isn't even needed. you filter your csv with Where-Object already, just keep passing those objects down the pipeline to the export.

Since it sounds like you are just running this against all the child folders of the parent, sounds like you could just use the -Recurse parameter of Get-ChildItem

Get-ChildItem '\\servername\volume\dir1\audit\serverbeingaudited\' -Recurse |
    ForEach-Object {
        Import-csv $_.FullName |
            Where-Object {$_.'path/from' -like "*01May18.xlsx*"} 
    } | Export-CSV -Path c:\temp\output.csv 

(I used a ForEach-Object loop rather than foreach just demonstrate objects being passed down the pipeline in another way)

Edit: Removed append per Bill_Stewart's suggestion. Will write out all entries for the the recursed folders in the run. Will overwrite on next run.

I don't see a need for appending the CSV file? How about:

Get-ChildItem '\\servername\volume\dir1\audit\serverbeingaudited\20180525' | ForEach-Object {
  Import-Csv $_.FullName | Where-Object { $_.'path/from' -like '*01May18.xlsx*' }
} | Export-Csv 'C:\Temp\Output.csv' -NoTypeInformation

Assuming your CSVs are in the same format and that your search text is not likely to be present in any other columns you could use a Select-String instead of Import-Csv . So instead of converting string to object and back to string again, you can just process as strings. You would need to add an additional line to fake the header row, something like this:

$files = Get-ChildItem '\\servername\volume\dir1\audit\serverbeingaudited\20180525'

$result = @()
$result += Get-Content $files[0] -TotalCount 1 

$result += ($files | Select-String -Pattern '01May18\.xlsx').Line 
$result | Out-File 'c:\temp\output.csv'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM