PowerShell. Массовое пережатие картинок
Дано:
- директория на файловом сервере с кучей картинок большого размера (.bmp размером под 26 метров)
Надо:
- пережать картинки в меньший размер
- название картинок и их местоположение на файловом сервере не должно измениться
- качество картинки не должно страдать
Нам понадобиться:
- powershell
- imagemagic. В составе данного ПО идет замечательная утилита convert.exe
- Ставим на свой ПК ПО Imagemagic
- Подключаем нужную нам папку как сетевой диск Z:
- Для понимания масштаба трагедии посмотрим какие и сколько файлов с изображениями у нас есть в данной папке
cls $path="Y:" $file_size = 4194304 #file_size = 4Mb Get-Childitem -Path $path -Recurse | Where-Object {$_.Length -ge $file_size -and $_.extension -in ".png",".bmp",".jpeg" -and !$_.PsIsContainer} | Select-Object Directory,Name,Length,FullName | Export-Csv D:\Big_pictures.csv -NoTypeInformation -Encoding UTF8
$file_size — указываем больше какого объема считаем файл большим. Т.е. если картинка весит больше 4 Мб, значит она попадет в лог. Размер указывается в байтах
$_.extension -in «.png»,».bmp»,».jpeg» — указываем какого расширения нас интересуют картинки - Пережимаем картинки. На данном этапе ничего с сетевого диска удаляться не будет
cls # ---------------------------------------- # Configuration $srcfolder = "Y:" $destfolder = "D:\Picture_resize" $im_convert_exe = "C:\Program Files\ImageMagick-7.0.1-Q16\convert.exe" $src_filter = "*.jpeg,*.bmp,*.png" $file_size = 4194304 $dest_ext = "jpeg" $options = "-quality 50" $logfile = "D:\convert_data.txt" # ---------------------------------------- $fp = New-Item -ItemType file $logfile -force $count=0 #foreach ($srcitem in $(Get-ChildItem $srcfolder -include $src_filter -recurse)) foreach ($srcitem in $(Get-ChildItem $srcfolder -include *.jpeg,*.bmp,*.png -recurse) | Where-Object {$_.Length -ge $file_size}) { $srcname = $srcitem.fullname # Construct the filename and filepath for the output $partial = $srcitem.FullName.Substring( $srcfolder.Length ) $destname = $destfolder + $partial $destname= [System.IO.Path]::ChangeExtension( $destname , $dest_ext ) $destpath = [System.IO.Path]::GetDirectoryName( $destname ) # Create the destination path if it does not exist if (-not (test-path $destpath)) { New-Item $destpath -type directory | Out-Null } # Perform the conversion by calling an external tool $cmdline = "convert.exe '$srcname' $options '$destname'" invoke-expression -command $cmdline # Get information about the output file $destitem = Get-item $destname # Show and record information comparing the input and output files $info = [string]::Format( "{0} `t {1} `t {2} `t {3} `t {4} `t {5}", $count, $partial, $srcname, $destname, $srcitem.Length , $destitem.Length) echo $info Add-Content $fp $info $count=$count+1 }
$options= «-quality 50» — методом научного тыка установлено, что при данном значении качество картинки не страдает. Можно указать еще кучу других опций, т.к. размер ВхШ в пикселях, кол-во пикселей на дюйм и т.д. Что теоретически может сэкономить нам заветные байты места на сетевом хранилище.
- $dest_ext = «jpeg» — указываем предпочитаемый формат изобраний
- Все пережатые экземпляры картинок упали в D:\Picture_resize. Смотрим, оцениваем качество. Если все устраивает, то из файла D:\convert_data.txt или из D:\Big_pictures.csv (что проще) вытаскиваем полный путь до больших картинок и копируем их в файл D:\Files_for_delete.txt
- Удаляем большие файлы с сетевого диска
cls # ---------------------------------------- $files = Get-Content D:\Files_for_delete.txt Foreach ($file in $files){ Remove-item $file }
- переносим все файлы из папки D:\Picture_resize в корень диска Y. Таким образом мы сохраним все структуру директорий и местоположение файлов.