Powershell - скрипт для сортировки фотографий по размерам, имеющий проблемы с оценкой "чисел"
Я пытаюсь написать скрипт Powershell для сортировки тысяч фотографий в соответствующие папки по ширине их изображения.
Мне бы хотелось:
- фотографии шириной до 300px классифицируются как маленькие.
- фотографии размером от 301 до 799 пикселей классифицируются как средние.
- фотографии размером 800px и выше должны быть классифицированы как большие.
Я нашел эту замечательную функцию, которую я использую: статья MS technet
Проблема в том, что у Powershell, похоже, возникают проблемы с правильной оценкой чисел / изображений шириной более 1000 пикселей.
Код, который у меня есть, здесь (по общему признанию, не очень красивый / упрощенный):
Function Get-FileMetaData
{
Param([string[]]$folder)
foreach($sFolder in $folder)
{
$a = 0
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace($sFolder)
foreach ($File in $objFolder.items())
{
$FileMetaData = New-Object PSOBJECT
for ($a ; $a -le 266; $a++)
{
if($objFolder.getDetailsOf($File, $a))
{
$hash += @{$($objFolder.getDetailsOf($objFolder.items, $a)) =
$($objFolder.getDetailsOf($File, $a)) }
$FileMetaData | Add-Member $hash
$hash.clear()
} #end if
} #end for
$a=0
$FileMetaData
} #end foreach $file
} #end foreach $sfolder
} #end Get-FileMetaData
$photodir="C:\photos\"
Get-FileMetaData -folder $photodir | select path,dimensions |
ForEach-Object -Process {
if ($_.dimensions -ne $null){
$filename=$_.path;
$dimensions=$($_.dimensions);
$dimensions_split=$dimensions.split();
$dimensions_width=$($dimensions_split[0]);
if ($dimensions_width -gt "799"){"$filename is $dimensions_width so is large";"---";}
if (($dimensions_width -lt "800") -and ($dimensions_width -gt "300")){"$filename is $dimensions_width so is medium";"---";}
if ($dimensions_width -lt "300"){"$filename is $dimensions_width so is small";"---";}
Это дает результаты:
C:\photos\logo1024x1024.jpg is 1024 so is small
---
C:\photos\logo128x128.jpg is 128 so is small
---
C:\photos\logo1600x1600.jpg is 1600 so is small
---
C:\photos\logo1920x1080.jpg is 1920 so is small
---
C:\photos\logo512x512.jpg is 512 so is medium
---
C:\photos\logo960x960.jpg is 960 so is large
---
Так что я подумал, может быть, это проблема, потому что они строки. Что, если я заставлю их быть целыми числами, надеюсь, что Powershell сможет их правильно оценить:
if ([int]$dimensions_width -gt 800){"$filename is $dimensions_width so is large";"---";}
Это дает ошибку:
Cannot convert value "1024" to type "System.Int32". Error: "Input string was
not in a correct format."
At C:\scripts\sort_photos_sm_md_lg.ps1:39
char:9
+ if ([int]$dimensions_width -gt 799){"$filename is $dimensions_width so
is la ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
Что не имеет смысла для меня, так как 1024 выглядит как целое число для меня?
Если я сделаю это таким образом, Powershell понравится синтаксис, но все равно не сможет правильно его оценить:
if (($dimensions_width -as [int]) -gt 799){"$filename is $dimensions_width so is large";"---";}
Несмотря на просмотр нескольких страниц результатов Google, я не могу найти ответ.
Кто-нибудь может помочь?
3 ответа
Что касается обходного пути, GDI + может использоваться для чтения большого разнообразия метаданных файла. Просто открываем файл какDrawing.Bitmap
обеспечивает размеры тоже. Вот так,
# Load the drawing assembly
add-type -assemblyname System.Drawing
# Open the image
$img = new-object Drawing.Bitmap("C:\MyBigImage.jpg")
# Print dimensions
$("w:{0} h:{1}" -f $img.Width, $img.Height)
w:3264 h:2448 # Quite big a picture
# Don't forget to dispose the bitmap
$img.Dispose()
Попробуй это:
$photodir= "C:\photos"
Get-FileMetaData -folder $photodir | select percorso,dimensioni |
ForEach-Object -Process {
if ($_.dimensioni -ne $null)
{
$filename=$_.percorso;
$dimensions=$($_.dimensioni);
$dimensions_width= [int](-join ((( $dimensions -split ' ' )[0]).ToCharArray() )[1..4])
}
switch ($dimensions_width)
{
{$_ -gt 799} {"$filename is $dimensions_width so is large";"---";break}
{$_ -lt 800 -and $dimensions_width -gt 300} {"$filename is $dimensions_width so is medium";"---";break}
default {"$filename is $dimensions_width so is small"; "---";break}
}
}
Проблема, упомянутая @Raf, является недопустимым символом после разбиения, но это не пробел, а [char][int]8234
значение, которое не зависит от trim()
метод.
Скорее всего, вы ведете или преследуете нелегального персонажа внутри $dimensions_width
, Вы можете проверить это, повторив $dimensions_width.Length
который является количеством символов в строке:
...
$dimensions_width=$($dimensions_split[0]);
Write-Host ("Width " + $dimensions_width + ",Length " + $dimensions_width.Length)
if ($dimensions_width -gt "799")....
....
Если на 1024 вы получите длину больше 4, то так и будет. Пытаться
$dimensions_width=$($dimensions_split[0].Trim() -replace "`n|`r|`t","");
избавиться от пробелов.