Powershell check whether a file exists - powershell

On Windows 7 x64, Powershell 3.0:
I have a directory where I download files to, this is done with a .csv file.
A sample of the files is:
008KS04.zip
008KS05.zip
008KS06.zip
008KS07.zip
008KS08.zip
008KS09.zip
I have a Csv, op wich this is a sample:
Documentnummer,Versie,Status,Geocode,IDS datum,Documentgroep (Omsch),Documenttype (Wrd),Tekeningnummer
550164,I,AB,008,26.03.2016,Themalagen OI,KS,008KS09.zip
550163,D,AB,008,19.07.2013,Themalagen OI,KS,008KS08.zip
550162,D,AB,008,19.07.2013,Themalagen OI,KS,008KS07.zip
550161,C,AB,008,19.07.2013,Themalagen OI,KS,008KS06.zip
550160,D,AB,008,19.07.2013,Themalagen OI,KS,008KS05.zip
550159,E,AB,008,15.08.2014,Themalagen OI,KS,008KS04.zip
So, lets say the files are in c:\test\
and the csv in C:\drawings.csv
I want the files that are missing in a csv, lets say C:\missing.csv
At first I tried with one drawing in a variable:
$drawnr = '008KS09.zip'
$destcsv = "C:\missing.csv"
Set-Location C:\test
If(Test-Path -Path ${drawnr}) {
Write-Output "${drawnr}'.zip' exists"
} Else {
Write-Output "${drawnr}'.zip' doesnt exist"
${drawnr} | Export-Csv $destcsv -Append -NoTypeInformation
}
The output when having an existing and a non existsing drawing in the variable
This works perfect, see image but using the CSV as input, I can't get it to work.
This is what I have so far:
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | Select-object -Property Tekeningnummer | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
If (Test-Path -Path ${_}) {
Write-Output "${_} does exist"
} Else {
Write-Output "${_} doesnt exist"
${_} | Export-Csv $destcsv -Append -NoTypeInformation
}
}
This tells me that none of the files exist, while all do exist.
See the picture to see the output of PowerShell and the content written to the missing.csv
The picture of the output where all files are reported as non existend

I'm not sure I get your intent, but it looks like this might work.
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
$TK = $_.Tekeningnummer
If (Test-Path -Path $TK) {
Write-Output "$TK does exist"
} Else {
Write-Output "$TK doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}

not sure if ${_} is a new syntax I'm not aware of but I can't get it to work on my PS4 host so I'm changing that to the normal $_ in my answer. beyond that you just need to do an ExpandProperty as #DaveSexton suggests.
Import-Csv $sourcecsv | Select-object -ExpandProperty Tekeningnummer | ForEach {
Write-Output "$($_) is the current object" #For Testing purpuse
If (Test-Path -Path $($_) {
Write-Output "$($_) does exist"
} Else {
Write-Output "$($_) doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}

just do it ;)
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
$dirtest='C:\test\'
Import-Csv $sourcecsv | where {-not (Test-Path "$dirtest$($_.Tekeningnummer)") } | export-csv $destcsv -NoTypeInformation

Related

Powershell - how to log for each object

I'm slowly getting to grips with Powershell but I cant see how to capture the for-each loop in a log (its probably something straight forward). My current code creates the log but doesnt seem to write to it - any ideas where I am going wrong?
$CSVImp = Import-Csv -Path "C:\Support\Powershell-Rename\Data.csv"
$OutputLog = ".\output.log"
Write $CSVImp | Where-Object { $_.CompName -eq $env:computername } | ForEach-Object {Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction SilentlyContinue } | Out-File $OutputLog -Append
Thanks
The scriptblock you pass to ForEach-Object can have as many statements as you like:
... |ForEach-Object {
Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction SilentlyContinue
if($?){
"[+] Successfully renamed '$($_.FileLocation)' to '$($_.FileRename)'"
}
else {
"[!] Failed to rename '$($_.FileLocation)' to '$($_.FileRename)'"
}
} |Out-File $OutputLog -Append
I'd suggest something like this where you use a Try/Catch block to log your entries.
Updated re: Mathias' comment. Hope I got it right!
$CSVImp = Import-Csv -Path "C:\Support\Powershell-Rename\Data.csv"
$OutputLog = ".\output.log"
$CSVImp | Where-Object { $_.CompName -eq $env:computername } |
ForEach-Object {
Try {
$MsgTrailer = "Rename $($_.FileLocation) to $($_.FileRename)"
Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction Stop
"Success: $MsgTrailer" |
Out-File $OutputLog -Append
}
Catch {
"Failed: $MsgTrailer" | Out-File $OutputLog -Append
}
Note: Untested code!

Export non-existent file paths to text file from Powershell

Trying to locate existent OR non-existent directories via powershell and a CSV file with the supposed directories. We can get it to run and display in the console, but it will not export the findings to a txt file. It creates the file, but it is empty. Any help is useful!
Import-Csv .\missingpaths.csv | ForEach {If (Test-Path -Path $_.Path) {Write-Output"$($_.Path) exists" } Else {Write-Output "$($_.Path) does NOT exist" $_.File | Out-File .\MissingCSV.csv -Append }}
The Out-File on your code is on the else statement only (one of he reasons why formatting and indentation is important is because it can help you prevent these issues) unless this was intentional and you only wanted to export those paths that do not exist.
} Else {
Write-Output "$($_.Path) does NOT exist" $_.File |
Out-File .\MissingCSV.csv -Append
}
Give this a try:
Import-Csv .\missingpaths.csv | ForEach-Object {
[pscustomobject]#{
Path = $_.Path
TestPath = ('Does not Exist', 'Exist')[(Test-Path $_.Path)]
}
} | Export-Csv path/to/result.csv -NoTypeInformation

How to check duplicate multiple file using powershell?

I want to check duplicate file.If the condition of the file like this, it means duplicate. The same name but different extension.
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
I can figure out this case with my script. But I have problem if I have this more than 1 .XML file like this
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
AAA18WWQ6BT601.XML
AAA18WWQ6BT604.XML
This case, it will not detect that file AAA18WWQ6BT602.PRO and AAA18WWQ6BT602.XML duplicated.
Anyone can help me please.
Thanks
$duplicate = #()
#(Get-ChildItem "$Flag_Path\*.xml") | ForEach-Object { $duplicate += $_.basename }
if(Test-Path -Path "$Flag_Path\*$duplicate*" -Exclude *.xml)
{
Get-ChildItem -Path "$Flag_Path\*$duplicate*" -Include *.xml | Out-File $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue for Error_Monitoring"
pause
Error_Monitoring
}
else{
Write-Host "Flag does not duplicate, continue the process"
}
The -Include parameter only works if the path on Get-ChildItem ends in \* OR if the -Recurse switch is used.
The following should do what you want:
$flagFolder = 'D:\*'
$dupeReport = 'D:\Flag_Duplicate.txt'
$duplicates = Get-ChildItem -Path $flagFolder -File -Include '*.xml', '*.pro' |
Group-Object -Property BaseName | Where-Object { $_.Count -gt 1 }
if ($duplicates) {
# output the duplicate XML to Flag_Duplicate.txt
$duplicates.Group | Where-Object {$_.Extension -eq '.xml' } | ForEach-Object {
$_.FullName | Out-File -FilePath $dupeReport -Append
}
# do the rest of your code
Write-Host "Flag duplicated, continue for Error_Monitoring"
Error_Monitoring
}
else {
Write-Host "Flag does not duplicate, continue the process"
}
Your script does not iterate correctly. You need to have an iteration to check. The Test-Path logic looks mixed up to me. I tried to keep as much of your code as possible.
This script checks for a any xml basename filename against any suffix duplicate (not only pro):
$Flag_Path = "C:\dir_to_be_checked"
$xmlFilesArray = #()
$allFilesExceptXml = #() # all files excluding xml files
# Get all the xml files
Get-ChildItem -Path $Flag_Path -Include "*.xml" | ForEach-Object { $xmlFilesArray += $_.basename }
# Get all files from the directory the xml files
Get-ChildItem -Path $Flag_Path -Exclude "*.xml" | ForEach-Object { $allFilesExceptXml += $_.basename }
# Iterate over list of files names without suffix
ForEach ($xmlFile in $xmlFilesArray) {
ForEach ($fileToCheck in $allFilesExceptXml) {
If ($xmlFile -eq $fileToCheck) {
# logging the duplicate file (specifying utf8 or the output would be UTF-16)
Write-Output "$Flag_Path\$xmlFile.xml" | Out-File -Append -Encoding utf8 $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue with duplicate search"
# pause
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Error_Monitoring
} Else {
Write-Host "Flag is not duplicated. Continue with the search."
}
}
}

Delete Files Older Than X Days: Presentation of Data/Logging Files

I'm new to Powershell, I'm creating a code to delete a file/s if more than "x" days.
I'm almost done. Need your help in representing my date (table) and should not produce a log file if no files will be delete.
Here's my code:
$max_days = "-30"
$curr_date = Get-Date
$del_date = $curr_date.AddDays($max_days)
$Path = "C:\Desktop\Code"
$DateTime = Get-Date -Format "D=yyyy-MM-dd_T=HH-mm-ss"
$itemsearch = Get-ChildItem C:\Test -Recurse | Where-Object { $_.LastWriteTime -lt $del_date}
Foreach ($item in $itemsearch)
{
Write "File:", $item.Name "Modified:", $item.LastWriteTime "Path:", $item.FullName "Date Deleted:" $del_date | Out-File "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.txt" -append
$item | Remove-Item
}
Can anyone please help me? It's already working by the way.
Just need to present the data in table form and don't create a log file if there's nothing to delete.
Update:
Already solved the condition statement by doing:
if($itemsearch)
{
Foreach ($item in $itemsearch)
{
Write "File:", $item.Name "Modified:", $item.LastWriteTime "Path:", $item.FullName "Date Deleted:" $del_date | Out-File "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.txt" -append
$item | Remove-Item
}
}
else
{
Write "No files will be deleted."
}
Thanks!
What I want to display it in Excel/Text file is like this one:
http://i59.tinypic.com/30wv33d.jpg
Anyone?
It returns me with this one:
IsReadOnly;"IsFixedSize";"IsSynchronized";"Keys";"Values";"SyncRoot";"Count"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
In Excel. Do you have any idea? I have to search it though.
To introduce tabular logging I would use a CSV file as output by replacing your foreach block by this code:
$results = #()
foreach ($item in $itemsearch)
{
$success = $true
try
{
$item | Remove-Item
}
catch
{
$success = $false
}
if( $success -eq $true )
{
Write-Host $item.FullName 'successfully deleted.'
$results += [PSCustomObject]#{'File'=$item.Name;'Modified'=$item.LastWriteTime;'Path'=$item.FullName;'Date Deleted'=$del_date;'State'='SUCCESS'}
}
else
{
Write-Host 'Error deleting' $item.FullName
$results += [PSCustomObject]#{'File'=$item.Name;'Modified'=$item.LastWriteTime;'Path'=$item.FullName;'Date Deleted'=$del_date;'State'='ERROR'}
}
}
$results | Export-Csv -Path "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.csv" -Encoding UTF8 -Delimiter ';' -NoTypeInformation
First an empty array is created ($results).
The try/catch block is here to detect if the deletion succeeded or not, then the appropriate line is added to $results.
At the end the $results array is exported to CSV with ';' separator so you can open it right away with Excel.

pipe foreach loop CSV PowerShell

I've written a script but cannot get it to export to CSV or output in any way.
PowerShell does not like foreach loops and exporting.
For each "folderpath/filename" in the .txt file it checks to see if the file is still there and outputs true or false + folderpath/file name.
Script works fine, just cannot get the thing to export to CSV.
Any ideas what I'm doing wrong?
foreach ($WantFile in Get-Content "C:\scripts\folderpaths.txt") {
$FileExists = Test-Path $WantFile
if ($FileExists -eq $True) {
Write-Output $wantfile "True"
} else {
Write-Output $wantfile "False"
}
} | Export-Csv C:\scripts\output.csv -noType
Change your code to this:
Get-Content 'C:\scripts\folderpaths.txt' | % {
if (Test-Path -LiteralPath $_) {
Write-Output $_ "True"
} else {
Write-Output $_ "False"
}
} | Export-Csv 'C:\scripts\output.csv' -NoType
I doubt that the resulting file will contain what you expect, though. Export-Csv exports the properties of objects. The output you generate are string objects (2 with each Write-Output statement, actually), and their only property is Length, so your result will be one column with the lengths of the strings you echo.
To create a CSV with 2 columns, one for path and the other for existence of the path you need to create objects with the desired properties, e.g. like this:
Get-Content 'C:\scripts\folderpaths.txt' `
| select #{n='Path';e={$_}}, #{n='Exists';e={Test-Path -LiteralPath $_}} `
| Export-Csv 'C:\scripts\output.csv' -NoType
With regard to the original question (exporting the output of a foreach loop to CSV), you can make that output to the pipeline by wrapping it in a subexpression, but that's not going to solve the other problems in your script with regard to what it is you're trying to export:
$(ForEach ($WantFile in Get-Content "C:\scripts\folderpaths.txt"){
$FileExists = Test-Path $WantFile
If ($FileExists -eq $True) {Write-Output $wantfile "True"}
Else {Write-Output $wantfile "False"}
})| export-csv C:\scripts\output.csv -noType
I got the same problem and i got it worked by doing as follow.
$forloop = foreach ( $i in $computers)
{
$i
$out = .\psexec.exe \\$i C:\hp\hpsmh\bin\smhlogreader.exe --version
$out
}
$forloop | Out-file C:\scripts\output.txt -Append