Powershell Get-ChildItem returns object not array - arrays

It seems Get-ChildItem returns a single object instead of an array of one object if it only finds one item. For example this returns 5:
$files = Get-ChildItem -Filter "e*.txt"
$files.length
But the following should return 1 but returns 61321:
$files = Get-ChildItem -Filter "exact.txt"
$files.length
The 61321 is the size in bytes of the file exact.txt.
How can we consistently check if there were files found?

It is a "feature" of Get-ChildItem that it won't return an array with one item but instead the single object. To force an array append # as in:
$files = #(Get-ChildItem -Filter "e*.txt")
Alternatively if you just want to check if there are NO files you can do:
$files = Get-ChildItem -Filter "exact.txt"
if (!$files) {"No Files"}

Related

Cannot remove a string from an array in powershell

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}

Powershell build array with each item a new line [duplicate]

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 (...)

How to extract properties from a powershell object

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

Storing Directory Folder Names Into Array Powershell

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.

Comma delimited input for a powershell function

I currently have a function that I made that gets a list of all files in a directory and then adds them to an array called $FileListArray.
I want to add an option that lets me specify the file extensions to exclude from the arrary so that I could call the function as follows ListFiles -FilesToList "c:\test" –exclude “avi,txt,bmp” and this would then ignore files with any of the file extensions I have put in.
My Function so far
Function ListFiles($FilesToList){
$FileListArray = #()
Foreach($file in Get-ChildItem $FilesToList -Force -Recurse | Where-Object {$_.attributes -notlike "Directory"})
{
$FileListArray += ,#($file.name,$file.fullname,$File.Extension)
}
}
Listfiles -FilesToList "c:\tools"
Try this:
Function ListFiles($Path,$Exclude)
{
Get-ChildItem -Path $FilesToList -Force -Recurse |
Where-Object {!$_.PSIsContainer -and $_.Extension -notmatch ($Exclude -join '|') }
}
Listfiles -Pathc:\tools –Exclude avi,txt,bmp

Resources