I'm checking for missing XYZ map tiles using Powershell, but coming unstuck in the nested loops. Essentially the map tiles exist from a "base" folder, within this base folder are multiple directories. Within each directory are the map tiles.
e.g.
C:\My Map\17\ # this is the Base folder, zoom level 17
C:\My Map\17\1234\ # this is a folder containing map tiles
C:\My Map\17\1234\30200.png # this is a map tile
C:\My Map\17\1234\30201.png # this is a map tile
C:\My Map\17\1234\30203.png # this is a map tile, but we're missing 30202.png (have tiles either side)
C:\My Map\17\1234\30204.png # this is a map tile
C:\My Map\17\1235\ # this is another folder containing map tiles [...]
So my idea is for each folder, scan for gaps where we have tiles each side and try to download them.
This is what I have so far:
$BasePath = "C:\_test\17\"
$ColumnDirectories = Get-ChildItem $BasePath -Directory
$ColumnDirectories | ForEach-Object {
$ColumnDirectory = $ColumnDirectories.FullName
$MapTiles = Get-ChildItem -Path $ColumnDirectory -Filter *.png -file
$MapTiles | ForEach-Object {
#Write-Host $MapTiles.FullName
$TileName = $MapTiles.Name -replace '.png',''
$TileNamePlus1 = [int]$TileName 1
$TileNamePlus2 = [int]$TileName 2
Write-Host $TileName
}
}
But I'm getting Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32".
Eventually I want to go Test-Path on each of $TileName, TileNamePlus1, $TileNamePlus2, and where the middle one doesn't exist to download it again.
e.g.
C:\My Map\17\1234\30201.png -- Exists
C:\My Map\17\1234\30202.png -- Not exists, download from https://somemapsrv.com/17/1234/30202.png
C:\My Map\17\1234\30203.png -- Exists
Any help appreciated! I'm fairly new to Powershell.
CodePudding user response:
The whole problem here is an understanding of how ForEach-Object
loops work. Within the loop the automatic variable $_
represents the current iteration of the loop. So as suggested by the comments by dugas and Santiago Squarzon you need to change this line:
$TileName = $MapTiles.Name -replace '.png',''
to this:
$TileName = $_.Name -replace '\.png',''
Or more simply this (the BaseName property is the file name without the extension):
$TileName = $_.BaseName
CodePudding user response:
Since all your png files have basenames as integer numbers, you could do something like this:
$BasePath = 'C:\_test\17'
$missing = Get-ChildItem -Path $BasePath -Directory | ForEach-Object {
$ColumnDirectory = $_.FullName
# get an array of the files in the folder, take the BaseName only
$MapTiles = (Get-ChildItem -Path $ColumnDirectory -Filter '*.png' -File).BaseName
# create an array of integer numbers taken from the files BaseName
$sequence = $MapTiles | ForEach-Object { [int]$_ } | Sort-Object
$sequence[0]..$sequence[-1] | Where-Object { $MapTiles -notcontains $_ } | ForEach-Object {
Join-Path -Path $ColumnDirectory -ChildPath ('{0}.png' -f $_)
}
}
# missing in this example has only one file, but could also be an array of missing sequential numbered files
$missing # --> C:\_test\17\1234\30202.png
If your file names have leading zero's, this won't work..