Check if a folder exists or not in the NAS from a CSV of users - powershell

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.

Related

Powershell - Test-Path with Import-CSV - remove #{Path= when importing

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"

Check if folder exists based on a partial string, create new folder if it doesn't, change name if it does

Short version: I'm trying to get a looping if/else statement to work. What I'm trying to get it to do is check to see if a folder exists that contains a particular string ending in a three-digit number (the variable $FolderSeqSRC below); if it doesn't, I want to create a folder with that string as its name. If it does, I want it to increment up the three-digit number and then go through the process again. This is the code that I have:
$FolderDate = (Get-Date).ToString('yyMMdd');
$FolderSeqSRC = 1;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$FolderDescript = "Test"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$FolderSearchName = "$FolderDate-$FolderSeq"
$OldFileName = "C0";
$NewFileName = "$FolderDate-$FolderSeq-";
Write-Host "$FolderDate";
Write-Host "$NewFolderName";
while (-not $completed) {
if (-Not (Test-Path -Path $targetDir\$FolderSearchName*)) {
"Path $FolderSearchName doesn't exist: creation in progress."
$completed = $true
} else {
"Path $FolderSearchName exists!"
$FolderSeqSRC++;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$FolderSearchName = "$FolderDate-$FolderSeq"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$NewFileName = "$FolderDate-$FolderSeq-";
"Trying path $FolderSearchName next."
$completed = $false
}
New-Item -ItemType Directory -Force -Path "$targetDir\$NewFolderName"
$completed = $true
}
I'm halfway home. It checks successfully to see if a folder exists with a -001 in it, and if it doesn't, it creates it exactly the way I want. If the 001 folder does exist, it creates a -002 folder. The problem is it won't increment past -002. I thought I had it set up properly to loop, but apparently I'm missing something. An earlier attempt had it stuck in an endless loop that DID increment properly, so I know this is close.
(This is part of a larger script that retrieves files off a camera SD card so some of these variables may look extraneous but aren't.)
Okay so turns out as usual I was overthinking things. This is what finally made it happen:
$FolderDate = (Get-Date).ToString('yyMMdd');
$FolderSeqSRC = 1;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$FolderSearchName = "$FolderDate-"
Write-Host "$FolderDate";
Write-Host "$NewFolderName";
$CheckPath = #(Get-ChildItem $targetDir -Recurse | Where-Object { $_.PSIsContainer -and $_.Name.StartsWith($FolderSearchName)}).Count;
Write-Host "Number of Existing Items: $CheckPath";
$FolderSeqSRC2 = $FolderSeqSRC + $CheckPath;
$FolderSeq = ([string]$FolderSeqSRC2).PadLeft(3,'0');
Write-Host "Increment should be: $FolderSeq"
PAUSE
$FolderSearchName = "$FolderDate-$FolderSeq"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$NewFileName = "$FolderDate-$FolderSeq-";
New-Item -ItemType Directory -Force -Path "$targetDir\$NewFolderName"
The answer was to simply not rely on an if/else loop--instead I found a way to tell Get-ChildItem to tell me how many folder names matched the partial string of the just the date, and then add that number to 1. The idea being that if it doesn't find any, then it adds 0, and the folder it creates is -001. If it finds two existing folders, it adds 2+1, to get me the new folder name 230106-003.

Change a value of an .ini files in multiple directories

I need to change a value in the DefaultPrint.ini file in multiple users "home" directory.
I've managed to make a powershell script to change the value on a single user, but I am struggeling making the script accept multiple users.
$User = "Max"
$IniPath = "\\Network1\Home\$User\"
foreach ($User in $User)
{
$IniFile = "$IniPath\DefaultPrint.ini"
$IniText = Get-Content -Path $IniFile
$NewText = $IniText.Replace("Old_Priter","New_Printer")
Set-Content -Path $IniFile -Value $NewText -Force
}
The directories I need to enter to find the files is based on the usernames, so I need to change the file in:
\Network1\Home\Max
\Network1\Home\John
\Network1\Home\Sophia
etc
The script above is working for a single user, and I am trying to adapt it to work with multiple users though a .csv file
I tried the following
$User = "Max","John","Sophia"
But it does not seperate the user directories but gathers them togther? (\Network1\Home\Max John Sophia)
I also tried to import via csv, as I need to do this on 200+ users
$User = (Import-Csv -Path .\Users.csv).User
But it ends up doing the same, what am I doing wrong?
You need to move this statement:
$IniPath = "\\Network1\Home\$User\"
inside the loop, so that the path is updated with the correct $user every time, and then rename the $User variable used outside the loop ($Users seems an appropriate name here):
$Users = -split "Max John Sophia"
foreach ($User in $Users)
{
$IniPath = "\\Network1\Home\$User\"
$IniFile = "$IniPath\DefaultPrint.ini"
$IniText = Get-Content -Path $IniFile
$NewText = $IniText.Replace("Old_Priter","New_Printer")
Set-Content -Path $IniFile -Value $NewText -Force
}

Import-CSV and ForEach providing unexpected output

I'm new here, and this is my first question. I looked through various related questions, but was not able to find an answer, so I'm hopeful that someone can help.
I have a script to create folders for user accounts, and assign them privileges. I have a .csv file with the names of the folders I want to create. When I run the script, it is not producing the desired results, but I'm not sure where I'm going wrong.
Contents of .csv file (each on a separate line):
1001
1002
1003...
There are no headers, just the numbers.
PS Script I'm running:
$csv = Import-Csv "E:\Support\usersOnly.csv" -Header #("Name")
ForEach ($line in $csv) {E:\Support\CreateFolders.ps1 -Path E:\blah\blahblah\$line -Access mydomain\$line -Permission modify}
This calls the folder creation script, which looks like this (I found this, it's not mine):
param ([string]$Path, [string]$Access, [string]$Permission = ("Modify"), [switch]$help)
function GetHelp() {
$HelpText = #"
DESCRIPTION:
NAME: CreateFolder.ps1
Create Folders and sets permissions for user.
PARAMETERS:
-Path Folder to Create or Modify (Required)
-User User who should have access (Required)
-Permission Specify Permission for User, Default set to Modify (Optional)
-help Prints the HelpFile (Optional)
SYNTAX:
./CreateFolder.ps1 -Path C:\Folder\NewFolder -Access Domain\UserName -Permission FullControl
Creates the folder C:\Folder\NewFolder if it doesn't exist.
Sets Full Control for Domain\UserName
./CreateFolder.ps1 -Path C:\Folder\NewFolder -Access Domain\UserName
Creates the folder C:\Folder\NewFolder if it doesn't exist.
Sets Modify (Default Value) for Domain\UserName
./CreateFolder.ps1 -help
Displays the help topic for the script
Below Are Available Values for -Permission
"#
$HelpText
[system.enum]::getnames([System.Security.AccessControl.FileSystemRights])
}
function CreateFolder ([string]$Path) {
# Check if the folder Exists
if (Test-Path $Path) {
Write-Host "Folder: $Path Already Exists" -ForeGroundColor Yellow
} else {
Write-Host "Creating $Path" -Foregroundcolor Green
New-Item -Path $Path -type directory | Out-Null
}
}
function SetAcl ([string]$Path, [string]$Access, [string]$Permission) {
# Get ACL on FOlder
$GetACL = Get-Acl $Path
# Set up AccessRule
$Allinherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$Allpropagation = [system.security.accesscontrol.PropagationFlags]"None"
$AccessRule = New-Object system.security.AccessControl.FileSystemAccessRule($Access, $Permission, $AllInherit, $Allpropagation, "Allow")
# Check if Access Already Exists
if ($GetACL.Access | Where { $_.IdentityReference -eq $Access}) {
Write-Host "Modifying Permissions For: $Access" -ForeGroundColor Yellow
$AccessModification = New-Object system.security.AccessControl.AccessControlModification
$AccessModification.value__ = 2
$Modification = $False
$GetACL.ModifyAccessRule($AccessModification, $AccessRule, [ref]$Modification) | Out-Null
} else {
Write-Host "Adding Permission: $Permission For: $Access"
$GetACL.AddAccessRule($AccessRule)
}
Set-Acl -aclobject $GetACL -Path $Path
Write-Host "Permission: $Permission Set For: $Access" -ForeGroundColor Green
}
if ($help) { GetHelp }
if ($Path -AND $Access -AND $Permission) {
CreateFolder $Path
SetAcl $Path $Access $Permission
}
The output I'm getting is:
Permission: modify Set For: mydomain\#{Name=1018}
Creating E:\blah\blahblah\#{Name=1019}
Adding Permission: modify For: mydomain\#{Name=1019}
Exception calling "AddAccessRule" with "1" argument(s): "Some or all identity references could not be translated."
At E:\Support\CreateFolders.ps1:90 char:3
+ $GetACL.AddAccessRule($AccessRule)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : IdentityNotMappedException
Permission: modify Set For: mydomain\#{Name=1019}
Creating E:\blah\blahblah\#{Name=102}
Adding Permission: modify For: mydomain\#{Name=102}
It creates a folder with the name '#{Name=102}', when all I want is '102'.
I've also tried this without the header, by adding a line at the top of my .csv file called 'Name', but had no success there either. If I don't include a header, it tries to use the first folder name as the header.
If I run this script manually (without feeding it the .csv), it runs successfully, but I have over a thousand folders to create, so I'd rather automate. I'm sure this is something simple, as I'm new to PS scripting.
Thanks in advance for any help!
So, you have a CSV with no header and one column that you are importing. Currently the way you are importing it is populating $csv with and object array with the property name. The rest of your script is treating that as just a string array and ignoring the property. A minor change that would address this problem is to expand that column.
$csv = Import-Csv "E:\Support\usersOnly.csv" -Header #("Name") | Select-Object -ExpandProperty Name
But really since it is only one column and no header don't even bother with the CSV aspect of this (it really isn't a CSV anyway.)
$csv = Get-Content "E:\Support\usersOnly.csv"
Aside from the potential misleading variable name you should just have to change that one line for this to be correct. (Assuming there are not other problems.)
The #{Name=1018} you are seeing is the string representation (shown as a hashtable) of one of the elements in your $csv array.

PowerShell Wildcard Not Returning All Files

I'm new to PowerShell and been trying to get this script to work.
If ((Get-Date -UFormat %a) -eq "Mon") {$intSubtract = -3}
Else {$intSubtract = -1}
$datDate = (Get-Date).AddDays($intSubtract)
Write-Output "Find expected file --------------"
$strDate = ($datDate).ToString('yyyyMMdd')
Write-Host "strDate: $strDate"
$arrGetFile = Get-ChildItem -Path "\\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt"
$strLocalFileName = $arrGetFile
If ($arrGetFile.count -ne 2)
{
Throw "No file or more than two files with today's date exists!"
}
Else {$strLocalFileName = $arrGetFile[0].Name}
Write-Output "Found file $strLocalFileName --------------"
#Encrypt each file
foreach ($arrGetFile in $strPath)
{
Write-Output "Start Encrypt --------------"
$strPath = "\\Computer\Data\States\NorthDakota\Cities\"
$FileAndPath = Join-Path $strPath $strLocalFileName
$Recipient = "0xA49B4B5D"
Import-Module \\JAMS\C$\PSM_PGP.psm1
Get-Module Encrypt
Encrypt $FileAndPath $Recipient
$strLocalFileNamePGP = $strLocalFileName + ".pgp"
Write-Output "End Encrypt --------------"
}
#Archive files
Write-Output "Archiving --------------"
move-item -path \\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt -destination \\Computer\Data\States\NorthDakota\Cities\Archive
The Cities folder will contain two files. Example 2015_Bismark_20150626_183121.txt and 2015_Bismark_20150626_183121_Control.txt
I am trying to get both files encrypted however it is only finding and encrypting the file without _Control. It is archiving both files correctly.
Not sure what I am missing to also find the control file.
Your for loop is incorrect. You have foreach ($arrGetFile in $strPath), but $strPath doesn't seem to contain anything at that point.
Your for loop should be:
foreach ($LocalFile in $arrGetFile)
And you need to remove the following line:
$strLocalFileName = $arrGetFile
This is making $strLocalFileName an array of file objects, but later in the script you are treating it like a string. You may have more logical errors--you need to walk through the script very carefully and identify each variable and make sure it contains what you expect it to contain.
In general you seem to be treating arrays of non-string objects as if they are strings. Note that I changed your $strLocalFileName variable to $LocalFile. This is because it is a file object, not a string object.
Following is a sample that just shows that the for loop iterates through the both files.
If ((Get-Date -UFormat %a) -eq "Mon") {$intSubtract = -3}
Else {$intSubtract = -1}
$datDate = (Get-Date).AddDays($intSubtract)
Write-Output "Find expected file --------------"
$strDate = ($datDate).ToString('yyyyMMdd')
Write-Host "strDate: $strDate"
$arrGetFile = Get-ChildItem -Path "\\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt"
If ($arrGetFile.count -ne 2)
{
Throw "No file or more than two files with today's date exists!"
}
Write-Output "Found files " ($arrGetFile | select Name | fl) "--------------"
#Process each file
foreach ($LocalFile in $arrGetFile)
{
$FileAndPath = Join-Path $LocalFile.DirectoryName $LocalFile
$FileAndPath
}
Start with this and then carefully add your encryption processing back into the loop.
Also, The line that assigns $FileAndPath could be removed. You can just use $LocalFile.FullName wherever you need the full path and filename.