I'm trying to populate an array of file paths where ever the script is located in. But I don't want
the array to include the path of the script only the other files in that folder. I have tried removing it after it is populated by using a list array instead but then I get an error that the array is a fixed size.
#To get path in which the script is located
$mypath = $MyInvocation.MyCommand.Path
$myStringPath=$mypath.ToString().Replace("TestingScriptPath.ps1", "")
#Populates files inside the folder
$array = #()
(Get-ChildItem -Path $myStringPath ).FullName |
foreach{
$array += $_
}
#display paths
for($i = 0; $i -lt $array.length; $i++)
{
$array[$i]
}
You're better off not putting it in the array in the first place.
When updating an array the whole array has to be rewritten, so the performance tends to be terrible.
Use a different datatype if you're going to be removing item-by-item.
#To get path in which the script is located
$mypath = $MyInvocation.MyCommand.Path
$myStringPath=$mypath.ToString().Replace("testingscriptpath.ps1", "")
#Populates files inside the folder
$array = Get-ChildItem -Path $myStringPath | Where-Object {$_.fullname -ne $mypath}
$array
if you definitely want to do it the way suggested in the question (slower)
$ArrayWithFile = Get-ChildItem -Path $myStringPath
$ArrayWithoutFile = $ArrayWithFile | Where-Object {$_.fullName -ne $mypath}
Related
This question already has an answer here:
Powershell: Piping output of pracl command to array
(1 answer)
Closed 1 year ago.
Using Get-ChildItem I have pulled a list of files that meet a criteria, then split a part of the Basename and want to build an array with that part of the name. I can do that successfully, except the array returns on long string. I'd like each part of the array to return on a new line.
Script:
$files = GCI "\\Paths" -Recurse | Where-Object {$_.LastWriteTime -ge (Get-Date).Adddays(-22)}
$name = ""
foreach($file in $files){
$file = $file.basename.Split(".")[0]
$array += $file
}
I also tried the following with no luck:
$files = GCI "\\Paths" -Recurse | Where-Object {$_.LastWriteTime -ge (Get-Date).Adddays(-22)}
$name = ""
foreach($file in $files){
$file = $file.basename.Split(".")[0]
$array+= $file -split "`n"
}
Current outcome when calling $array:
file01file02file03file04
Desired outcome when calling $array:
file01
file02
file03
file04
The string is returned because $array is not an array. It is typed at assignment and its first assignment is a string. Therefore it keeps appending new values to that string.
You may do the following instead:
$array = foreach($file in $files){
$file.basename.Split(".")[0]
}
When iterated values are output within a foreach statement, that statement output can be captured into a variable. Each value will be an element of an array.
As an aside, the += syntax to add elements to an array is inefficient because a new array is created each time after retrieving all the contents of the current array.
You're already returning an array, so just narrow it down to what you're assigning to your variable.
$files = GCI "\\Paths" -Recurse |
Where-Object {$_.LastWriteTime -ge (Get-Date).Adddays(-22)} |
ForEach-Object -Process {
$_.basename.Split(".")[0]
}
Or, just assign a variable to your foreach loop removing the output to an array.:
$arr = foreach (...)
I am trying to extract properties of object from the results obtained from Get-ChildItem in Powershell as it may be seen below
$folderPath = "C:\Users\me\someThing1\someThing2"
$fileNames = Get-ChildItem -Path $folderPath -Filter *.pdf -recurse | ForEach-Object {
$_.FullName
$_.LastWriteTime
$_.Exists
$_.BaseName
$_.Extension
}
# Extracting properties
foreach ($file in $fileNames) {
Write-Host $file
}
When I use the Write-Host command, I get property values of FullName, LastWriteTime, Exists, BaseName, Extension printed to the terminal for each file. But I am unable to get individual property value.
For e.g., I tried
Write-Host $file."BaseName"
It does not work. Can someone help me extract individual property from each file?
The purpose is to store each property of each file into an array as given below
$FullNames = #()
$LastWriteTimes = #()
$Exists = #()
$BaseNames = #()
$Extensions = #()
Just posting the revised code that extracts properties into individual arrays just so that someone else might find it helpful. Thanks to all who supported.
# Edit the Folder Path as desired
$folderPath = "C:\Users\me\someThing1\someThing2"
# Getting File Objects
$files = Get-ChildItem -Path $folderPath -recurse
# Extracting properties into individual Arrays
$FullNames = $files.FullName
$LastWriteTimes = $files.LastWriteTime
$file_Exists = $files.Exists
$BaseNames = $files.BaseName
$Extensions = $files.Extension
I've a folder called c:\mycommands
files under this folder are multiple files like:
command1.txt
command2.txt
command3.txt
each file has one line only, like this:
in file command1.txt:
echo "this is command1"
in file command2.txt"
echo "this is command2"
and so on
I want to read the filename and it's content into an array/variable pair in order to build a dynamic menu.
so theoretically, all I would need to do in the future is to, drop a file into the folder and program will include it as menu option dynamically. (or remove the file to have it not show up in menu option.
What's the best way to approach this? maybe a do while loop with get-content into an array? Any input would be greatly appreciated. I'm really trying limit or avoid menu maintenance but would rather have the menu bre created dynamically
Here are three variations on the same basic idea, depending on what kind of output you need.
# Storing output in a hash table (key/value pairs)
$resultHash = #{}
Get-ChildItem -Path C:\mycommands -File |
ForEach-Object {$resultHash.Add($_.Name, (Get-Content -Path $_.FullName))}
# Storing output in an array of psobjects
$resultArray = #()
Get-ChildItem -Path C:\mycommands -File |
ForEach-Object {
$resultArray += (New-Object -TypeName psobject -Property #{"NameOfFile"=$_.Name; "CommandText"=(Get-Content -Path $_.FullName);})
}
# Outputting psobjects to the pipeline
Get-ChildItem -Path C:\mycommands -File |
ForEach-Object {
New-Object -TypeName psobject -Property #{"NameOfFile"=$_.Name; "CommandText"=(Get-Content -Path $_.FullName);}
}
# Making a nice menu out of the hash table version
$promptTitle = "My menu"
$promptMessage = "Choose from the options below"
$promptOptions = #()
foreach ($key in $resultHash.Keys)
{
$promptOptions += New-Object System.Management.Automation.Host.ChoiceDescription $key, $resultHash[$key]
}
$promptResponse = $host.ui.PromptForChoice($promptTitle, $promptMessage, $promptOptions, 0)
If I am understanding what you want correctly, this might be able to accomplish it for you.
If will gather a list of all the files in a folder, then get the content from each one and add them to an Array one by one.
[System.Collections.ArrayList]$Files = #(Get-ChildItem "C:\Logs\" |
Where-Object {$_.PSIsContainer -eq $false} |
Select-Object FullName)
[System.Collections.ArrayList]$List_Of_Commands = #()
foreach ($File in $Files) {
[System.Collections.ArrayList]$File_Contents = #(Get-Content $File.FullName)
foreach ($Content in $File_Contents) {
$Array_Object = [PSCustomObject]#{
'Command' = $Content
}
$List_Of_Commands.Add($Array_Object) | Out-Null
}
}
$List_Of_Commands
I have an array of folders, called $FolderArray. It contains about 40 folders. Inside each folder are a bunch of txt files. I want to loop through each folder to get the number of files in each folder, as well as the total size of each folder. I got the number of files in each folder to work, but for the folder size, it ends up outputting the file size of the last file in each folder.
I pulled this out of a larger snippet of my code, so if anything needs more clarification please let me know. I appreciate the help!
$ProcessedLocation = "C:\Users\User.Name\Documents"
$FolderArray = gci -Path $ProcessedLocation | Where-Object {$_.PSIsContainer} | Foreach-Object {$_.Name}
Foreach ($i in $FolderArray)
{
$FolderLocation = $ProcessedLocation + $i
[int]$FilesInFolder = 0
Get-ChildItem -Path $FolderLocation -Recurse -Include '*.txt' | % {
$FilesInFolder = $FilesInFolder + 1
$Length = $_.Length
$FolderSize = $FolderSize + $Length
}
Write-Host $FolderSize
}
You are iterating over $FolderArray twice, once in the foreach($i in $FolderArray) loop, and then again inside the loop body:
foreach($i in $FolderArray){
Get-ChildItem $FolderArray # don't do this
}
If you want to look into each folder in $FolderArray individually, reference the current variable (in your example that would be $i).
I would recommend saving the output from Get-ChildItem to a variable and then grab the size and count of the files from that:
# keep folders as DirectoryInfo objects rather than strings
$FolderArray = Get-ChildItem -Path $ProcessedLocation
foreach ($Folder in $FolderArray)
{
# retrieve all *.txt files in $Folder
$TxtFiles = Get-ChildItem -Path $Folder -Recurse -Include '*.txt'
# get the file count
$FilesInFolder = $TxtFiles.Count
# calculate folder size
$FolderSize = ($TxtFiles | Measure -Sum Length).Sum
# write folder size to host
$FolderSizeMB = $FolderSize / 1MB
Write-Host "$Folder is $FolderSizeMB MB in size"
}
I am trying to write a script that will get the names of all the folders in a specific directory and then return each as an entry in an array. From here I was going to use each array element to run a larger loop that uses each element as a parameter for a later function call. All of this is through powershell.
At the moment I have this code:
function Get-Directorys
{
$path = gci \\QNAP\wpbackup\
foreach ($item.name in $path)
{
$a = $item.name
}
}
The $path line is correct and gets me all of the directories, however the foreach loop is the problem where it actually stores the individual chars of the first directory instead of each directories full name to each element.
Here's another option using a pipeline:
$arr = Get-ChildItem \\QNAP\wpbackup |
Where-Object {$_.PSIsContainer} |
Foreach-Object {$_.Name}
$array = (dir *.txt).FullName
$array is now a list of paths for all text files in the directory.
For completeness, and readability:
This get all files in "somefolder" starting with 'F' to an array.
$FileNames = Get-ChildItem -Path '.\somefolder\' -Name 'F*' -File
This gets all directories of current directory:
$FileNames = Get-ChildItem -Path '.\' -Directory
# initialize the items variable with the
# contents of a directory
$items = Get-ChildItem -Path "c:\temp"
# enumerate the items array
foreach ($item in $items)
{
# if the item is a directory, then process it.
if ($item.Attributes -eq "Directory")
{
Write-Host $item.Name//displaying
$array=$item.Name//storing in array
}
}
I believe the problem is that your foreach loop variable is $item.name. What you want is a loop variable named $item, and you will access the name property on each one.
I.e.,
foreach ($item in $path)
{
$item.name
}
Also take note that I've left $item.name unassigned. In Powershell, if the result isn't stored in a variable, piped to another command, or otherwise captured, it is included in the function's return value.