I have a list of files that I am breaking up into parts. That works, but I want to be able to reference each part individually. The issue is with my array not wanting/being able to take in a string. The file naming format is custID_invID_prodID or custID_invID_prodID_Boolvalue.
$files = Get-ChildItem test *.txt
[string]$custId = $files.Count
[string]$invID = $files.Count
[string]$prodID = $files.Count
[int]$Boolvalue = $files.Count
foreach($file in (Get-ChildItem test *.txt)) {
for($i = 0; $i -le $files.Count; $i++){
$custId[$i], $invID[$i], $prodID[$i], $Boolvalue[$i] = $file.BaseName -split "_"
Write-Host $custId, $invID, $prodID, $Boolvalue
}
}
The error message I am seeing is:
Unable to index into an object of type System.String.
How can I do this?
To create a string array, we can declare the variable name. Another way is to create using the @(). One more way is by creating the system. collections.
Creating PowerShell ArrayList Collections Collections namespace within . NET. By creating a new object of this type you can then store objects within an ArrayList. Below you can see that you need to explicitly create an ArrayList object using the New-Object cmdlet or by casting a standard array to an ArrayList object.
In PowerShell, you can assign values to multiple variables using a single command. The first element of the assignment value is assigned to the first variable, the second element is assigned to the second variable, the third element to the third variable. This is known as multiple assignment.
Array subexpression operator @( )Returns the result of one or more statements as an array. The result is always an array of 0 or more objects. PowerShell Copy.
I'd suggest working with objects instead of a lot of string arrays. I have an example below in which I have replaced the file listing, since I don't have the file structure in place, with an ordinary array. Just remove that array declaration and put in your Get-ChildItem
call and it should work just fine.
function ConvertTo-MyTypeOfItem
{
PARAM (
[ValidatePattern("([^_]+_){3}[^_]+")]
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$StringToParse
)
PROCESS {
$custId, $invId, $prodId, [int]$value = $StringToParse -split "_"
$myObject = New-Object PSObject -Property @{
CustomerID = $custId;
InvoiceID = $invId;
ProductID = $prodId;
Value = $value
}
Write-Output $myObject
}
}
# In the test scenario I have replaced getting the list of files
# with an array of names. Just uncomment the first and second lines
# following this comment and remove the other $baseNames setter, to
# get the $baseNames from the file listing
#$files = Get-ChildItem test *.txt
#$baseNames = $files.BaseName
$baseNames = @(
"cust1_inv1_prod1_1";
"cust2_inv2_prod2_2";
"cust3_inv3_prod3_3";
"cust4_inv4_prod4_4";
)
$myObjectArray = $baseNames | ConvertTo-MyTypeOfItem
$myObjectArray
The above function will return objects with the CustomerID
, InvoiceID
, ProductID
and Value
properties. In the sample above, the function is called and the returned array value is set to the $myObjectArray/code> variable. When output in the console it will give the following output:
InvoiceID CustomerID ProductID Value --------- ---------- --------- ----- inv1 cust1 prod1 1 inv2 cust2 prod2 2 inv3 cust3 prod3 3 inv4 cust4 prod4 4
Seems to me that you're doing it the hard way. Why 4 arrays for every "field" of a file? It's better to create array of arrays - first index would indicate a file, and second a field in file:
$files = Get-ChildItem test *.txt
$arrFiles = @(,@());
foreach($file in $files ) {
$arrFile = $file.BaseName -split "_"
$arrFiles += ,$arrFile;
}
Write-Host "listing all parts from file 1:"
foreach ($part in $arrFiles[1]) {
Write-Host $part
}
Write-Host "listing part 0 from all files":
for ($i=0; $i -lt $arrFiles.Count ; $i++) {
Write-Host $arrFiles[$i][0];
}
Because you're trying to index into an object of type System.String! You set all your variables as strings to start with and then try to assign to an index, which I presume would attempt to assign a string to the character position at the index you provide.
This is untested but should be in the right direction.
$custIdArr = @()
$invIDArr = @()
$prodIDArr = @()
$BoolvalueArr = @()
foreach($file in (Get-ChildItem test*.txt)) {
$split = $file.BaseName -split "_"
$custId = $split[0]; $custIdArr += $custId
$invID = $split[1]; $invIDArr += $invId
$prodID = $split[2]; $prodIDArr += $prodID
$boolValue = $split[3]; $boolValueArr += $boolValue
Write-Host $custId, $invID, $prodID, $Boolvalue
}
Create a set of empty arrays, loop through your directory, split the filename for each file, append the results of the split into the relevant array.
I'm assigning to $custId, $invID, $prodID, $Boolvalue
for the sake of clarity above, you may choose to directly add to the array from the $split
var i.e. $invIDArr += $split[1]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With