Search code examples
arraysstringpowershellcommand-linetostring

Array of characters instead of array of strings


I am trying to get a list of SMB shares on a remote file server. Unfortunately because of the type of server I am querying WMI and CIM won't work. The only thing I can get to work is net view (which I believe uses netbios).

I am running the following code which gets the shares:

$shares = net view \\server1 /all | select -Skip 7 | ?{$_ -match 'disk*'} | %{$_ -match '^(.+?)\s+Disk*'|out-null;"\\server1\$($matches[1])"}
$shares += net view \\server2 /all | select -Skip 7 | ?{$_ -match 'disk*'} | %{$_ -match '^(.+?)\s+Disk*'|out-null;"\\server2\$($matches[1])"}


foreach ($share in $shares) {
    $logdir1 = @("$share\App_Data\","errorlogs")
    $logdirs = @($logdir1)

    foreach ($log in $logdirs) {
        write-host $log[0]

However, instead of getting a list of paths, I am getting the first character of each path. So basically $log[0] is a character - not a string as I an expecting.

I think this has to do with the net view command returning characters instead of an object.

I tried using ToString() in various places to no avail. Anyone help me figure out how to get this to work?

Thanks!


Solution

  • Update:

    Your problem came down to the misconception that @(...), the array-subexpression operator is an array constructor, which it is not: instead, think of it as an array guarantor.

    Thus, replace:

    $logdirs = @($logdir1) # WRONG: same as $logDirs = $logdir1 in this case.
    

    with:

    $logdirs = , $logdir1
    

    ... in order to create a nested array whose one and only element is the two-element array contained in $logDir, using , the array constructor operator, which you can then enumerate with foreach and refer to its elements with [0] and [1].

    For background information on @(...), see this answer.


    Original answer:

    $logdir1 = @("$share\App_Data\","errorlogs")
    $logdirs = @($logdir1)
    

    ... can be reduced to $logdirs = @("$share\App_Data\", "errorlogs")

        foreach ($log in $logdirs) {
    

    ... then enumerates the elements of the array of string values in $logDirs

        write-host $log[0]
    

    ... then refers to the first character ([0]) of the string value at hand (indexing into a string extracts the character at the specified position; e.g., 'abc'[1] yields 'b')

    Therefore, everything works as expected.

    Perhaps you meant to enumerate the files inside the directory referenced by each $log value (renamed to $logDir for clarity below)?

    foreach ($logdir in $logdirs) {
      $filesInDir = Get-ChildItem -File -LiteralPath $logdir
      $filesInDir[0]
    }