I am creating simple powershell to grab data from a CSV(list of directories) and pass it into Test-Path to check if the path exists. However, the path from the csv is passing in...differently.
$csvdata = Import-Csv "C:\X\testfolder.csv"
foreach($entry in $csvdata){
If(Test-Path "'($entry)'"){
Write-Host $entry ' Folder exists'
}
Else{
Write-Host ($entry) ' Folder does not exist'
}
}
test-path "C:\X\testfolder.csv"
This is what I get
#{Path=C:\X} Folder does not exist
#{Path=C:\X\testing} Folder does not exist
Obviously, the issue is the "#{Path=" being passed in. Is there a proper way to grab those rows or should I remove them after the fact? If so, how?
Thank you.
Each $entry object represents an entire row. To get just the value of a particular column, use the column header as a property name, eg.:
Write-Host "Folder '$($entry.Path)' does not exist"
Related
The task is to track the execution of SQL backups. One of the tracking mechanisms is to browse the directory where the backups are saved and if the file is missing, you can send an email with the full address of the directory where the file is missing. This is what I am trying to implement with Powershell script, but for some reason my script doesn't work and doesn't give me the information I need.
$list = Get-ChildItem -Path network_path_to_share -Recurse -File | Where-Object {$_.DirectoryName -like '*FULL*' -and $_.LastWriteTime -ge (Get-Date).AddDays(-6)}
$fileExists = Test-Path $list
If ($fileExists)
{
#Do Nothing
}
Else
{
$list | Select DirectoryName
}
Can anyone help?
I suppose what you need is to test each file or path individually. You take Get-ChildItem with recurse, so it returns multiple files and stores them in $list.
If you do something like
Foreach ($item in $list) {
$fileexists = Test-Path $item
If ($fileexists -eq $false) {
do something }
}
You should be good to go. This would cycle through all items and does whatever you need to be done. If you compare against $false, you wouldn't need the else statement, and you could also just put "Test-Path" into the if-statement like
If (Test-Path $item -eq $false) {}
Edit: Sorry I accidentally posted the answer before finishing it lol
Also, as stackprotector correctly points out, Get-ChildItem can only retrieve items that exist, because how should it detect missing files.
If you're wanting to check for something that is missing or doesn't exist, you need to start with a known condition, e.g.: either the server names or expected file or directory names.
If you know that, then you can create a static list (or dynamically query a list from Active Directory for your SQL servers or something (assuming the backup file names correspond to the server names)) and then check the files that were created and output the missing ones for triage.
Here is a modification to your script (essentially the opposite of what you did) that might point you in the right direction:
## List of expected files
$ExpectedFiles = #(
'File1.bak',
'File2.bak',
'File3.bak',
'File4.bak'
'...'
)
## Get a list of created files
$list = Get-ChildItem -Path network_path_to_share -Recurse -File | Where-Object {$_.DirectoryName -like '*FULL*' -and $_.LastWriteTime -ge (Get-Date).AddDays(-6)} | Select -ExpandProperty Name
## Check whether each expected file exists in the array of backups that actually were created
foreach ($file in $ExpectedFiles) {
if (-not(Test-Path $list)) {
"$($file) is missing!"
}
}
I have to make a script that checks if a file exists in our NAS from a CSV file which contains a list a users.
I have made this small script but the result is kind of broken, I don't
understand why the typo is "{user=USER10}" and not just "USER10"
This is the result from the script:
This is my CSV of users
The script:
$sInputFile = "D:\Script\ADD2000.csv"
$sColumnName = "User"
$tblUsers = Import-Csv $sInputFile
$FolderPath = "\\somepath.tech.intra.workplace.fr\users$\ADD"
$Retrieve = Test-Path $Path
foreach($user in $tblUsers){
$Path = $FolderPath + "\" + $($user) + ".ADD2000"
if (!(Test-Path $Path)) {
write-host "$path does not exist"
} Else {write-host "it exist"}
}
Looking at the image of your input CSV, I can see it has a header user. When importing that csv, all items in that column are objects with one property called user.
To get the value of that, you need to expand it like $user.user.
In your case, since you have only one column in the file, it would even be simpler if you expand the values straight away when importing, so you can iterate over a string array of usernames.
$sInputFile = 'X:\Folder\AllUsers.csv' # full path to the input csv file
$tblUsers = (Import-Csv $sInputFile).user # just get the values of all items for column 'user' as striong array
$FolderPath = '\\somepath.tech.intra.workplace.fr\users$\ADD'
foreach($userName in $tblUsers) {
$path = Join-Path -Path $FolderPath -ChildPath "$username.ADD2000"
if (Test-Path $Path -PathType Container) {
Write-Host "$path exists"
}
else {
Write-Warning "$path could not be found"
}
}
You are importing a CSV with a column "User".
You need to return the value from that column e.g. $($user.User) not just $($user).
$user contains the entire row $user.User contains just the value from that column.
I have a script that I use to search for hundreds of files across multiple drives from a list. It works fine as it catches all the matches. The only issue is I need to see the file it matched along with the extension.
A bit of the back story...
We have programs that share the same name as a Copybook. Not too uncommon in the mainframe world. When searching for a file, I have to Wildcard the search in order to catch all the same name files (Minus the extension). I then have to manually search for the hits to determine if they are copybooks or programs.
When I try to add any logic to the script below, it displays the entire array of file names and not just the actual match.
Would anyone be able to assist in capturing and displaying just the matched file along with it's extension? Maybe it's location also?
Regards,
-Ron
#List containing file names must be wilcarded FILE.*
#Parent folder (Where to begin search)
$folder = 'C:\Workspace\src'
#Missing Artifacts Folder (Where Text file resides)
$Dir2 = 'C:\Workspace\Temp'
#Text File Name
$files=Get-Content $Dir2\FilesToSearchFor.txt
cd \
cd $folder
Write-Host "Folder: $folder"
# Get only files and only their names
$folderFiles = (Get-ChildItem -Recurse $folder -File).Name
foreach ($f in $files) {
#if ($folderFiles -contains $f) {
if ($folderFiles -like $f) {
Write-Host "File $f was found." -foregroundcolor green
} else {
Write-Host "File $f was not found!" -foregroundcolor red
}
}
Instead of testing whether the entire list of file names contains the target file name ($folderFiles -like $f), load all files into a hashtable and then test if the target file name exists as a key with ContainsKey():
$fileTable = #{}
Get-ChildItem -Recurse $folder -File |ForEach-Object {
# Create a new key-value entry for the given file name (minus the extension) if it doesn't already exist
if(-not $fileTable.ContainsKey($_.BaseName)){
$fileTable[$_.BaseName] = #()
}
# Add file info object to the hashtable entry
$fileTable[$_.BaseName] += $_
}
foreach($f in $files){
if($fileTable.ContainsKey($f)){
Write-Host "$($fileTable[$f].Count) file(s) matching '$f' were found." -ForegroundColor Green
foreach($file in $fileTable[$f]){
Write-Host "File with extension '$($file.Extension)' found at: '$($file.FullName)'"
}
}
else {
Write-Host "No files found matching '$f'"
}
}
Since the $fileTable contains not just the name, but also a reference to the original file info objects with that names as returned by Get-ChildItem, you can easily access relevant metadata (like the Extension property) now
How can you use Test-Path (or any other function) to test if a folder exists - ignoring any trailing file names?
I need this to test if the target folder exists in order to write an output file to it. My script accepts a "full path" parameter like "C:\Temp\myexport.csv", and I only need to know that C:\Temp exists in order to be able to create the file.
Thank you
try this :
$OutFile = "C:\Temp\myexport.csv"
$Dir=[System.IO.Path]::GetDirectoryName($OutFile)
if(!(Test-Path $Dir)) {
Write-Host "Invalid path"
}
Nevermind.. I didn't Google hard enough:
$OutFile = "C:\Temp\myexport.csv"
if(!Test-Path -Path (Split-Path -Path $OutFile)) {
Write-Host "Invalid path"
}
We are deleting a load of XP profiles to save disk space. Some profile folders for XP exist as well as those for the same user with the .V2 for windows 7. Id like to use powershell to return only those XP profiles that exist.
Here is my code so far
$path = "\\server01\profiles"
#Get User Folder names into variable for ForEach Loop
$UserFolders = get-childitem -path $path\*.V2 | where-object {$_.Psiscontainer -eq "True"} |select-object name
#Loop through folders in Directory
foreach ($UserFolder in $UserFolders){
#remove the last .V2 from the folder name
$UserFolder = $UserFolder.name.substring(0,$UserFolder.name.length-3)
write-output $path\$userfolder
test-path $path\$userfolder #returns True or false
}
I just cant get the last bit to work. How can I only display only those folders that exist (return True)
You just need to rearrange things so that Write-Output only occurs if Test-Path validates that a path exists. I won't add anything new to your code except for an if statement, as an example:
foreach ($UserFolder in $UserFolders){
$UserFolder = $UserFolder.name.substring(0,$UserFolder.name.length-3)
if (test-path $path\$userfolder)
{
# Code at this level will only be executed if Test-Path was true.
write-output $path\$userfolder
}
}
So by placing write-output into the scope of the if statement, we ensure that it will only be executed if Test-Path is true.