get-childitem either subfolder or a "rbac.jsonc" file - powershell

I want to check if all folders contains either a subfolder or an rbac.jsonc file.
I want to iterate through a list of folder $topMgFolderPath being the root folder.
I want to go all the way down the tree in the folders
I am are looking to trigger a Pester test failure if there is anything that do not correspond to my condition.
I expect folders to have either a rbac.json file, in which case all the subfolders in that folder will be ignored from any further processing or at least 1 subfolder that will itself contains either a rbac.jsonc file or more subfolders that will lead down the line to such a file.
In all cases, .policy folder is to be ignored
is this somehow possible ?

Your question lack some clarity for me as it stand.
Based on your post, what I understand is:
You want to iterate through a list of folder $topMgFolderPath being the root folder.
You used -Recurse in your code sample so I assumed you want to go all the way down the tree
Based on your second code line ending of | should -BeNullOrEmpty, you are looking to trigger a Pester test failure if there is anything that do not correspond to your condition.
You expect folders to have either a rbac.json file, in which case all the subfolders in that folder will be ignored from any further processing or at least 1 subfolder that will itself contains either a rbac.json file or more subfolders that will lead down the line to such a file.
In all cases, .policy folder is to be ignored
Please update your question with additional details or clarify the situation if I didn't get the premise right.
In any case, what you seek to do is possible but not through a single Get-ChildItem statement.
The way I'd go about it, since you want a recurse operation with multiple checks that stop processing a folder once it has been validated, is an home-made -recurse done through a single-layer Get-ChildItem alongside a queue where the recursion is done "manually", one layer at a time within a while loop that persist until the queue is cleared out.
$topMgFolderPath = 'C:\temp\'
$queue = [System.Collections.Queue]::new()
$InvalidFolders = [System.Collections.Generic.List[PSobject]]::new()
$Directories = Get-ChildItem -path $topMgFolderPath -Exclude '.policy' -Directory
$Directories | % { $queue.Enqueue($_.FullName) }
while ($Queue.Count -gt 0) {
$dir = $queue.Dequeue()
$HasRbacFile = Test-Path -Path "$dir\rbac.json"
# If Rbac file exist, we stop processing this item
if ($HasRbacFile) { Continue }
$SubDirectories = Get-ChildItem -Path $dir -Directory -Exclude '.policy'
# If the rbac file was not found and no subfolders exist, then it is invalid
if ($SubDirectories.count -eq 0) {
$InvalidFolders.Add($dir)
} else {
# Subdirectories found are enqueued so we can check them
$SubDirectories | % {$queue.Enqueue($_.FullName)}
}
}
# Based on your second line of code where you performed that validation.
$InvalidFolders | should -BeNullOrEmpty
Everything important happens in the while loop where the main logic
Is there a rbac file ?
If not, is there any subfolders (not .policy) to check ?
References
Queue Class

Related

Moving files to folders based on a filename

Howdy all of you smart people! I am a bit out of my depth and thought I would ask a question to see if someone with a higher IQ could at least point me in the right direction.
I have a share with a lot of single lvl subfolders all with similar names in format (xxxxxx_x)
Inside of each folder there are several files:
half will start with the same prefix "xxxxxx_x" as the parent folder
other half has another prefix of 10 digits followed by the parent folder prefix:"yyyyyyyyyy-xxxxxx_x"
I was asked to move files to a new location where I have already scripted a deployment of same folder structure but of course the new ask is for the files to be split based on the above two naming conventions.
TL;DR:
So to summarize, how can I move a batch of files from multiple subfolders to other location based on a part of the filename? (prefix)
typical example:
c:\share\123456_2\123456_2-filename.xls should go to d:\share\123456_2
while
c:\share\123456_2\1234567890-123456_2-filename.xls should go to E:\share\123456_2
I could get the files moved and folders created (if missing) using below but how do I only target files that start with the same string (0,8)?
dir | %{
$id = $_.Name.SubString(0,8);
if(-not (Test-Path $id)) {mkdir $id};
mv $_ "D:\share\$_";}
Well, one way to do this is using the -Split operator, or method to get just the first part of the broken string and check to see if it contains the underscore character (_); since that seems to follow the naming scheme.
Get-ChildItem |
ForEach-Object -Process {
$destination = $_.Name.Split('-')[0]
if ($destination -match "_") {
Move-Item -LiteralPath $_.FullName -Destination "D:\share\$destination" -WhatIf
}
}
Given that you're not looking to move the other files, this will only move the files that have the same beginning.
Remove the -WhatIf safety common parameter once you've dictated the results are what you're after.

Apply a file to multiple folders using better PowerShell script

I'm working on a project where I have to apply a file to multiple folders every so often. I'm trying to learn some PowerShell commands to make this a little easier. I came up with the following script, which works, but I feel that this is too verbose and could be distilled down with a better script:
[string]$sourceDirectory = "C:\Setup\App Folder Files\*"
# Create an array of folders
$destinationDirectories = #(
'C:\Users\GG_RCB1\Documents\',
'C:\Users\GG_RCB2\Documents\',
'C:\Users\LA_RCB1\Documents\',
'C:\Users\PR_RCB1\Documents\',
'C:\Users\PQ_RCB1\Documents\',
'C:\Users\PQ_RCB2\Documents\',
'C:\Users\XC_RCB1\Documents\',
'C:\Users\XC_RCB2\Documents\',
'C:\Users\XC_RCB3\Documents\',
'C:\Users\XC_RCB4\Documents\',
'C:\Users\XC_RCB5\Documents\',
'C:\Users\XC_RCB6\Documents\',
'C:\Users\XC_RCB7\Documents\',
'C:\Users\XC_RCB8\Documents\')
# Perform iteration to create the same file in each folder
foreach ($i in $destinationDirectories) {
Copy-item -Force -Recurse -Verbose $sourceDirectory -Destination $i
}
I go into this process knowing that every folder in the User folder area is going to have the same format: _RCB<#>\Documents\
I know that I can loop through those files using this code:
Get-ChildItem -Path 'C:\Users'| where-object {$_.Name -match "^[A-Z][A-Z]_RCB"}
What I'm not sure how to do is to how, within that loop, drill down to the Documents folder and do the copy. I want to avoid having to keep updating the array from the first code sample, particularly when I know the naming convention of the subfolders in the Users folder. I'm just looking for a cleaner way to do this.
Thanks for any suggestions!
Ehh, I'll go ahead and post what I had in mind as well. Not to take away from #Mathias suggestion in the comments, but to offer my solution, here's my take:
Get-ChildItem -Path "C:\users\[A-Z][A-Z]_RCB*\documents" |
Copy-Item -Path $sourceDirectory -Destination { $_.FullName } -Recurse -WhatIf
Since everyone loves the "One-Liners" that can accomplish your needs. Get-ChildItem accepts wildcard-expressions in it's path which let's us accomplish this in one go. Given that your directories are...
consistent with the same naming pattern,
[A-Z][A-Z]_*
and the folder destination is the same.
Documents
Luckily, Copy-Item also has some cool features on it's own such as being able to use a script block that will allow the passing of $_.FullName property as it's destination, while they are passed down the pipeline one at a time.
Remove the -WhatIf common parameter when you've dictated the results are what you're after.

Renaming files in bulk and in ascending order in CMD

I know this question was already asked by someone but I will ask again.
Can someone tell me how to rename in bulk and in ascending order if possible in CMD. I already tried renaming in powershell but to no avail. It only let me use once and I need to rename another folder files but to no avail. It didn't let it rename files in another folder. This is the code I use in powershell:
$i = 1
Get-ChildItem *.mkv | %{Rename-Item $_ -NewName ('Haikyuu - {0:D2}.mkv' -f $i++)}
I'm renaming my anime series per folder and some of my copies have 100+ videos. and somehow you could teach me what each code mean (the code that must use in CMD). The ones I've searched can't understand it in layman's term or doesn't tell the user how it's supposed to work. Thank you in advance. by the way, the folder is placed in an external drive.
so from the beginning:
$i= variable for storing the initial value 1
Get-ChildItem = is like "dir" which lists the files and folder under a certain path.
In this case, it is listing all the files which starts with anything but have the extension .mkv
* indicates wildcard.
| = pipeline which passes the output of the first command as an input of the next command.
% = ForEach-Object is iterating each object one by one coming from the pipeline.
$_= Current pipeline object . Here it is taking each object one by one and renaming it using Rename-Item
-NewName = is the parameter of the Rename-Item which asks for the new name to pass.
Hope it clarifies your need.
The reason why I can't rename my video files is there were [brackets] on the filename.
So I use this:
Get-ChildItem -Recurse -Include *.mkv | Rename-Item -NewName { $_.Name.replace("[","").replace("]","").replace("(","").replace(")","") }
Which on the same directories, I can access subfolders too to omit brackets and parethesis. then I proceed using the code above in the question to rename my files in every folder. The Reason why I'm doing the 'renaming' per folder is that, each folder is different anime series. but the code above is working.
if anyone can give me less code than repeating the 'replace' and concatenating it, I will gladly accept and choose that as the best answer. :)
If you use the parameter -LiteralPath for the source, no prior renaming is necessary.
%i = 1
Get-ChildItem *.mkv |
ForEach {Rename-Item -LiteralPath "$_" -NewName ('Haikyuu - {0:D2}.mkv' -f $i++)}
A hint on sorting, I hope the present numbering of the source files has a constant width, otherwise the result is mixed up as an alphabetic sort (which is inherent to ntfs formatted drives) will sort the number 10 in front of 2.
To check this append the parameter -whatif to the Rename-Item command

Simple script to move files from one location to another

I need help with creating a power-shell script that copies folder recursively from one location to another. Here is how I plan to do it:
There will be a list of folders to copy, which are combination of name and ID number.
Create an array to store variables.
Create a loop that will look for each variables in array and copy the folders to another location.
Here is my code to copy a single folder, but I need to make it more feasible so that it can copy folders depending on variables:
$AID = (4069302,4138482)
foreach ($number in $AID ) {
Get-ChildItem "C:\Users\sshres19\Desktop\Script\GAEBox" -Recurse -Filter "*$number*" |
Copy-Item -destination "C:\Users\sshres19\Desktop\Script\Reg"
}
The script needs to copy all folders and files within given condition.
Adding -Recurse to your Copy-Item will make it copy a folder and it's contents.

Powershell script to move files based on a source list (.txt

I have thousands of files in a directory (.pdf, .xls, .doc) and they all have a similar naming convention (the "type" is always a constant string, ie: billing or invoice);
accountname_accountnumber_type.pdf
accountname_ accountnumber_type.doc
accountname_accountnumber_type.xls
The task at hand is to receive a random list of accountnames and account numbers (the "type" is always a constant, ie: billing, invoice, shipping or order and they vary in format) and move them from Directory A into Directory B. I can get the list into a .csv file to match the accountname_accountnumber_type.
I have been trying to create a powershell script to reference the accountname_accountnumber and move those items from one directory A to directory B with no luck.
SAMPLE I found something a bit simpler, but I wanted to be able to edit this to create a new destination and not halt if the file is not found from this list. Also, if I could have this pick from a .txt list I think that would be easier than pasting everything.
$src_dir = "C:\DirA\"
$dst_dir = "D:\DirB-mm-dd-yyyy\" #This code requires the destination dir to already be there and I need to have the code output a new Directory, it could output based on date script run that would be amazing
$file_list = "accountname1_accountnumber001_type", #If I can select to import csv here
"accountname2_accountnumber002_type",
"accountname3_accountnumber003_type",
"accountname4_accountnumber004_type",
"accountname5_accountnumber005_type",
"accountname6_accountnumber006_type"
foreach ($file in $file_list) #This errors out and stops the script if the file is not located in source and I need to have the script continue and move on, with hopefully an error output
{
move-Item $src_dir$file $dst_dir
}
They can be any file format, I am trying to get the code to match ONLY the accountname and accountnumber since those two will define the exact customer. Whether it is invoice, billing or shipping doesn't matter since they want all files associated with that customer moved.
For Example there could be 4 of each for every account and the type format may vary from pdf, doc and xls, I need to move all files based on their first two indicators (accountname,accountnumber).
alice_001_invoice.pdf
alice_001_billing.doc
alice_001_shipping.pdf
alice_001_order.xls
George_245_invoice.pdf
George_245_billing.doc
George_245_shipping.pdf
George_245_order.xls
Bob_876_invoice.pdf
Bob_876_billing.doc
Bob_876_shipping.pdf
Bob_876_order.xls
Horman_482_invoice.pdf
Horman_482_billing.doc
Horman_482_shipping.pdf
Horman_482_order.xls
CSV:
accountname,accountnumber
Alice,001
George,245
Bob,876
Horman,482
How about this :
$CurrentDate = [DateTime]::Now.ToString("MM-dd-yyyy")
$DestinationDir = "D:\DirB-$CurrentDate"
New-Item $DestinationDir -ItemType Directory -ErrorAction SilentlyContinue
$AccountToMove = Import-CSV $CSVPath
Foreach ( $Account In $AccountToMove ){
$FilePattern = "*$($Account.AccountName)*$($Account.AccountNumber)*"
ls $SourceDir | Where Name -like $FilePattern | Move-Item -Destination $DestinationDir
}
The code part - you already edited off from the post - about moving files to subdirectories doesn't make much sense with your business rules. As you never show the sample CSV file contents, it's all guessing.
For easier processing, assume you got the following source files. Edit your post to show the CSV file contents and where you would like to move the files.
C:\some\path\A\Alice_001_bill.doc
C:\some\path\A\Alice_001_invoice.xls
C:\some\path\A\Bob_002_invoice.pdf
C:\some\path\A\Bob_002_invoice.doc
C:\some\path\A\Eve_003_bill.xls
C:\some\path\A\Eve_003_invoice.doc