Skip to main content

Bildsortierung

Kurze Vorwarnung dass dies hier überwiegend KI-generiertes Zeug ist. Hat funktioniert, muss aber nicht erneut funktionieren. Es ist wichtig dass ihr in Grundzügen nachvollziehen könnt, was die Scripts tun, auch wenn sie generiert sind.
Pastet diese Scripts z.B. in eine KI rein und lasst sie euch erklären. Easy as that... Nur kurz schildern wer ihr seid und was ihr beruflich macht und warum ihr euch jetzt unbedingt das Script anschauen müsst.

Generatoren: ChatGPT, Claude.ai, manchmal Llama, je nachdem was so passte.

 Das hier wird sicherlich irgendwann mal kombiniert in nem großen Script dass dann gewisse Auswahl zulässt.

Nach Bildauflösung

Fest definierte Größe

ChatGPT 3.5 als Hilfestellung

Skript sammelt Bilder die kleiner als festgelegte Auflösung sind in einem anderen Ordner und belässt die, die größer sind im Ordner.

Das Beispiel hier trennt Bilder >4K von denen die es nicht sind.

param (
	[string]$SourceFolder = "C:\Path\to\SourceFolder",
    [string]$DestinationFolder = "C:\Path\to\DestinationFolder",
    [int]$MinWidth = 3840,
    [int]$MinHeight = 2160
)

# Create the destination folder if it doesn't exist
if (-not (Test-Path $DestinationFolder)) {
    New-Item -ItemType Directory -Path $DestinationFolder | Out-Null
}

# Get all image files in the source folder and its subfolders
$images = Get-ChildItem -Path $SourceFolder -Filter "*.jpg" -File -Recurse

$totalImages = $images.Count
$processedImages = 0

# Process each image file
foreach ($image in $images) {
    Write-Host "Processing $($image.FullName)"

    # Use .NET classes to read image dimensions
    $imageStream = New-Object System.IO.FileStream($image.FullName, [System.IO.FileMode]::Open)
    $imageBitmap = New-Object System.Drawing.Bitmap($imageStream)
    $width = $imageBitmap.Width
    $height = $imageBitmap.Height
    $imageStream.Close()

    # Check if the image is smaller than the specified dimensions
    if ($width -lt $MinWidth -or $height -lt $MinHeight) {
        $destinationPath = Join-Path -Path $DestinationFolder -ChildPath $image.Name
        Write-Host "Moving $($image.FullName) to $destinationPath"
        Move-Item -Path $image.FullName -Destination $destinationPath
    }

    $processedImages++
    $progress = [math]::Round(($processedImages / $totalImages) * 100, 2)
    Write-Progress -Activity "Moving images" -Status "Progress: $progress%" -PercentComplete $progress
}

Write-Progress -Activity "Moving images" -Status "Progress: 100%" -PercentComplete 100
Write-Host "Image move complete!"

 

Auswahldialoge für Auflösung und Ordner

Claude 3.5 Sonnet

  1. Mindestauflösung Höhe und Breite in Pixeln auswählen
  2. Ordnerdialoge für Quell- und Zielordner wählen
  3. Alle Bilder, die die Mindestauflösung haben oder überschreiten, werden in den gewählten Zielordner verschoben

Fehler sind in ./error_log.txt

Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms

# Get the directory of the script
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$logFile = Join-Path $scriptPath "error_log.txt"

# Function to log errors
function Log-Error {
    param (
        [string]$message
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $message" | Out-File -FilePath $logFile -Append
}

# Function to show folder selection dialog
function Select-Folder {
    param (
        [string]$Description
    )
    $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
    $folderBrowser.Description = $Description
    $folderBrowser.RootFolder = [System.Environment+SpecialFolder]::MyComputer
    if ($folderBrowser.ShowDialog() -eq "OK") {
        return $folderBrowser.SelectedPath
    }
    return $null
}

# Prompt user for resolution
do {
    $targetWidth = Read-Host "Enter the target width in pixels (e.g., 3840 for 4K)"
} while (-not ($targetWidth -match '^\d+$'))

do {
    $targetHeight = Read-Host "Enter the target height in pixels (e.g., 2160 for 4K)"
} while (-not ($targetHeight -match '^\d+$'))

$targetWidth = [int]$targetWidth
$targetHeight = [int]$targetHeight

Write-Host "Target resolution: $targetWidth x $targetHeight"

# Prompt user to select source and destination folders
$sourceFolder = Select-Folder "Select the source folder containing images"
if (-not $sourceFolder) {
    Write-Host "Source folder selection cancelled. Exiting script."
    exit
}

$destinationFolder = Select-Folder "Select the destination folder for matching images"
if (-not $destinationFolder) {
    Write-Host "Destination folder selection cancelled. Exiting script."
    exit
}

# Create destination folder if it doesn't exist
if (!(Test-Path -Path $destinationFolder)) {
    New-Item -ItemType Directory -Path $destinationFolder | Out-Null
    Write-Host "Created destination folder: $destinationFolder"
}

# Get all image files in the source folder
$imageFiles = Get-ChildItem -Path $sourceFolder -Include *.jpg, *.jpeg, *.png, *.bmp -File -Recurse

if ($imageFiles.Count -eq 0) {
    $message = "No image files found in $sourceFolder"
    Write-Host $message
    Log-Error $message
    exit
}

Write-Host "Found $($imageFiles.Count) image files to process"

# Initialize counter and total
$i = 0
$total = $imageFiles.Count
$movedCount = 0

# Initialize progress bar
Write-Progress -Activity "Processing Images" -Status "0% Complete" -PercentComplete 0

foreach ($file in $imageFiles) {
    try {
        $image = $null
        try {
            $image = [System.Drawing.Image]::FromFile($file.FullName)
            $width = $image.Width
            $height = $image.Height
            
            # Check if image meets or exceeds target resolution
            if ($width -ge $targetWidth -and $height -ge $targetHeight) {
                # Close the image before moving
                $image.Dispose()
                $image = $null
                
                # Move the file to the destination folder
                Move-Item -Path $file.FullName -Destination $destinationFolder -Force
                Write-Host "Moved: $($file.Name) (${width}x${height})"
                $movedCount++
            }
        }
        finally {
            # Ensure image is disposed even if an error occurs
            if ($image -ne $null) {
                $image.Dispose()
            }
        }
    }
    catch {
        $errorMessage = "Error processing $($file.Name): $_"
        Write-Host $errorMessage
        Log-Error $errorMessage
    }
    
    # Update progress
    $i++
    $percentComplete = ($i / $total) * 100
    Write-Progress -Activity "Processing Images" -Status "$i of $total processed" -PercentComplete $percentComplete
}

Write-Progress -Activity "Processing Images" -Completed
Write-Host "Processing complete. Moved $movedCount out of $total images."
ungetestete BETA

Mit Claude Sonnet erweitert. Hinzu kommen Abfragen nach Ordnern und Auflösung, Erkennung der Bildschirmauflösung etc.

ungetesteter direkter AI output

Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms

# Get the directory of the script
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$logFile = Join-Path $scriptPath "error_log.txt"

# Function to log errors
function Log-Error {
    param (
        [string]$message
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $message" | Out-File -FilePath $logFile -Append
}

# Function to show folder selection dialog
function Select-Folder {
    param (
        [string]$Description
    )
    $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
    $folderBrowser.Description = $Description
    $folderBrowser.RootFolder = [System.Environment+SpecialFolder]::MyComputer
    if ($folderBrowser.ShowDialog() -eq "OK") {
        return $folderBrowser.SelectedPath
    }
    return $null
}

# Get current screen resolution
$currentResolution = (Get-WmiObject -Class Win32_VideoController).VideoModeDescription
$resolutionMatch = $currentResolution -match '(\d+)\s*x\s*(\d+)'
if ($resolutionMatch) {
    $currentWidth = [int]$Matches[1]
    $currentHeight = [int]$Matches[2]
    Write-Host "Current screen resolution: $currentWidth x $currentHeight"
    
    $useCurrentResolution = Read-Host "Do you want to use the current screen resolution? (Y/N)"
    if ($useCurrentResolution -eq 'Y' -or $useCurrentResolution -eq 'y') {
        $targetWidth = $currentWidth
        $targetHeight = $currentHeight
    }
}

# If not using current resolution, prompt user for resolution
if (-not $targetWidth -or -not $targetHeight) {
    do {
        $targetWidth = Read-Host "Enter the target width in pixels (e.g., 3840 for 4K)"
    } while (-not ($targetWidth -match '^\d+$'))

    do {
        $targetHeight = Read-Host "Enter the target height in pixels (e.g., 2160 for 4K)"
    } while (-not ($targetHeight -match '^\d+$'))

    $targetWidth = [int]$targetWidth
    $targetHeight = [int]$targetHeight
}

Write-Host "Target resolution: $targetWidth x $targetHeight"

# Prompt user to select source and destination folders
$sourceFolder = Select-Folder "Select the source folder containing images"
if (-not $sourceFolder) {
    Write-Host "Source folder selection cancelled. Exiting script."
    exit
}

$destinationFolder = Select-Folder "Select the destination folder for matching images"
if (-not $destinationFolder) {
    Write-Host "Destination folder selection cancelled. Exiting script."
    exit
}

# Create destination folder if it doesn't exist
if (!(Test-Path -Path $destinationFolder)) {
    New-Item -ItemType Directory -Path $destinationFolder | Out-Null
    Write-Host "Created destination folder: $destinationFolder"
}

# Get all image files in the source folder
$imageFiles = Get-ChildItem -Path $sourceFolder -Include *.jpg, *.jpeg, *.png, *.bmp -File -Recurse

if ($imageFiles.Count -eq 0) {
    $message = "No image files found in $sourceFolder"
    Write-Host $message
    Log-Error $message
    exit
}

Write-Host "Found $($imageFiles.Count) image files to process"

# Initialize counter and total
$i = 0
$total = $imageFiles.Count
$movedCount = 0

# Initialize progress bar
Write-Progress -Activity "Processing Images" -Status "0% Complete" -PercentComplete 0

foreach ($file in $imageFiles) {
    try {
        $image = $null
        try {
            $image = [System.Drawing.Image]::FromFile($file.FullName)
            $width = $image.Width
            $height = $image.Height
            
            # Check if image meets or exceeds target resolution
            if ($width -ge $targetWidth -and $height -ge $targetHeight) {
                # Close the image before moving
                $image.Dispose()
                $image = $null
                
                # Move the file to the destination folder
                Move-Item -Path $file.FullName -Destination $destinationFolder -Force
                Write-Host "Moved: $($file.Name) (${width}x${height})"
                $movedCount++
            }
        }
        finally {
            # Ensure image is disposed even if an error occurs
            if ($image -ne $null) {
                $image.Dispose()
            }
        }
    }
    catch {
        $errorMessage = "Error processing $($file.Name): $_"
        Write-Host $errorMessage
        Log-Error $errorMessage
    }
    
    # Update progress
    $i++
    $percentComplete = ($i / $total) * 100
    Write-Progress -Activity "Processing Images" -Status "$i of $total processed" -PercentComplete $percentComplete
}

Write-Progress -Activity "Processing Images" -Completed
Write-Host "Processing complete. Moved $movedCount out of $total images."

 

Bilder <4K verschieben

PYTHON, kein Powershell

pip install Pillow tqdm

import os
from PIL import Image
import shutil
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
# Import and disable the DecompressionBombWarning
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = None  # Disable the warning
ImageFile.LOAD_TRUNCATED_IMAGES = True  # Handle truncated images

def get_image_resolution(image_path):
    """Get the resolution of an image file."""
    try:
        with Image.open(image_path) as img:
            return img.size
    except Exception as e:
        print(f"Error reading {image_path}: {str(e)}")
        return None

def is_4k_or_higher(width, height):
    """Check if the resolution is 4K (3840x2160) or higher."""
    return width >= 3840 and height >= 2160

def process_image(image_path, destination_folder):
    """Process a single image and move it if not 4K."""
    try:
        resolution = get_image_resolution(image_path)
        if resolution is None:
            return
        
        width, height = resolution
        if not is_4k_or_higher(width, height):
            # Create destination folder if it doesn't exist
            Path(destination_folder).mkdir(parents=True, exist_ok=True)
            
            # Get destination path
            dest_path = os.path.join(destination_folder, os.path.basename(image_path))
            
            # Move file, overwriting if it exists
            shutil.move(image_path, dest_path)
            
    except Exception as e:
        print(f"Error processing {image_path}: {str(e)}")

def main():
    # Configuration
    source_folder = input("Enter the source folder path: ")
    destination_folder = input("Enter the destination folder for non-4K images: ")
    
    # Validate source folder
    if not os.path.exists(source_folder):
        print("Source folder does not exist!")
        return
    
    # Get list of image files
    image_files = [
        os.path.join(source_folder, f) 
        for f in os.listdir(source_folder) 
        if f.lower().endswith(('.png', '.jpg', '.jpeg'))
    ]
    
    if not image_files:
        print("No image files found in the source folder!")
        return
    
    print(f"Found {len(image_files)} images. Processing...")
    
    # Process images using thread pool for better performance
    with ThreadPoolExecutor(max_workers=8) as executor:
        list(tqdm(
            executor.map(
                lambda x: process_image(x, destination_folder),
                image_files
            ),
            total=len(image_files),
            desc="Processing images"
        ))
    
    print("Done! All non-4K images have been moved.")

if __name__ == "__main__":
    main()
Bilder >= 4K verschieben

PYTHON 
pip install Pillow tqdm

import os
from PIL import Image
import shutil
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
import warnings
import logging
import sys
from datetime import datetime
# Import and disable the DecompressionBombWarning
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = None  # Disable the warning
ImageFile.LOAD_TRUNCATED_IMAGES = True  # Handle truncated images

# Get the script's filename without extension to create log filename
script_path = sys.argv[0]
script_name = os.path.splitext(os.path.basename(script_path))[0]
log_filename = f"{script_name}_errors.log"

# Setup logging
logging.basicConfig(
    filename=log_filename,
    level=logging.WARNING,
    format='%(asctime)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

# Custom warning handler to redirect warnings to logging
def handle_warning(message, category, filename, lineno, file=None, line=None):
    logging.warning(f"Warning: {message}")

# Replace the default warning handler
warnings.showwarning = handle_warning

def get_image_resolution(image_path):
    """Get the resolution of an image file."""
    try:
        with Image.open(image_path) as img:
            return img.size
    except Exception as e:
        logging.error(f"Error reading image {image_path}: {str(e)}")
        return None

def is_4k_or_higher(width, height):
    """Check if the resolution is 4K (3840x2160) or higher."""
    return width >= 3840 and height >= 2160

def process_image(image_path, destination_folder):
    """Process a single image and move it if it IS 4K or higher."""
    try:
        resolution = get_image_resolution(image_path)
        if resolution is None:
            return
        
        width, height = resolution
        if is_4k_or_higher(width, height):
            # Create destination folder if it doesn't exist
            Path(destination_folder).mkdir(parents=True, exist_ok=True)
            
            # Get destination path
            dest_path = os.path.join(destination_folder, os.path.basename(image_path))
            
            # Move file, overwriting if it exists
            shutil.move(image_path, dest_path)
            
    except Exception as e:
        logging.error(f"Error processing {image_path}: {str(e)}")

def main():
    # Log script start
    logging.info(f"Script started at {datetime.now()}")
    
    # Configuration
    source_folder = input("Enter the source folder path: ")
    destination_folder = input("Enter the destination folder for 4K and higher resolution images: ")
    
    # Log folders
    logging.info(f"Source folder: {source_folder}")
    logging.info(f"Destination folder: {destination_folder}")
    
    # Validate source folder
    if not os.path.exists(source_folder):
        logging.error("Source folder does not exist!")
        print("Source folder does not exist!")
        return
    
    # Get list of image files
    image_files = [
        os.path.join(source_folder, f) 
        for f in os.listdir(source_folder) 
        if f.lower().endswith(('.png', '.jpg', '.jpeg'))
    ]
    
    if not image_files:
        logging.warning("No image files found in the source folder!")
        print("No image files found in the source folder!")
        return
    
    print(f"Found {len(image_files)} images. Processing...")
    logging.info(f"Found {len(image_files)} images to process")
    
    # Process images using thread pool for better performance
    with ThreadPoolExecutor(max_workers=8) as executor:
        list(tqdm(
            executor.map(
                lambda x: process_image(x, destination_folder),
                image_files
            ),
            total=len(image_files),
            desc="Processing images"
        ))
    
    logging.info(f"Script completed at {datetime.now()}")
    print("Done! All 4K and higher resolution images have been moved.")
    print(f"Check {log_filename} for any errors that occurred during processing.")

if __name__ == "__main__":
    main()

 

Dedup

macht man am besten mit Czkawka oder DupeGuru

Basic Dedup

ChatGPT 3.5

(falls Copy statt Move im Script vorab gemacht wurde)

Das Ding tut noch nicht das was ich will, womöglich komme ich selbst durcheinander mit Source und Destination. Ich setz also unten noch mal anders an.

param (
  # Mag etwas durcheinander und verkehrt sein. KI halt... Jedenfalls ist Destination der Ordner der über bleiben soll. und source der Ordner in dem die Duplikate liegen
    # Ordner in dem gelöscht wird.
    [string]$SourceFolder = "XXXXXXXXXXXXXXXXXXXXXXXXX",
    # Ordner gegen den Verglichen wird
    [string]$DestinationFolder = "XXXXXXXXXXXXXXXXXXXX",

)

# Get all image files in the destination folder
$destinationImages = Get-ChildItem -Path $DestinationFolder -Filter "*.jpg" -File

# Initialize counters for deleted images in each folder
$deletedInSourceFolderCount = 0
$deletedInDestinationFolderCount = 0

# Process each image file in the destination folder
foreach ($destinationImage in $destinationImages) {
    Write-Host "Processing $($destinationImage.FullName)"

    # Construct the source file path based on the destination file name
    $sourceFilePath = Join-Path -Path $SourceFolder -ChildPath $destinationImage.Name

    # Check if the corresponding file exists in the source folder
    if (Test-Path $sourceFilePath) {
        Write-Host "Deleting $($sourceFilePath)"
        # Remove the item (move to Recycle Bin)
        Remove-Item -Path $sourceFilePath -Force -Confirm:$false

        # Increment the counter for deleted images in the source folder
        $deletedInSourceFolderCount++
    }

    # Increment the counter for deleted images in the destination folder
    $deletedInDestinationFolderCount++
}

# Output the deletion statistics
Write-Host "Duplicate removal complete!"
Write-Host "Deleted $deletedInSourceFolderCount images in the source folder: $SourceFolder"

Prüfscripts

Prüfen ob keine Bilder >4K existieren

ChatGPT 3.5

$SourceFolder = "C:\Path\to\SourceFolder"
$MinWidth = 3840
$MinHeight = 2160

# Get all image files in the source folder and its subfolders
$images = Get-ChildItem -Path $SourceFolder -Filter "*.jpg" -File -Recurse

$totalImages = $images.Count
$processedImages = 0

# Process each image file
foreach ($image in $images) {
    # Use .NET classes to read image dimensions
    $imageStream = New-Object System.IO.FileStream($image.FullName, [System.IO.FileMode]::Open)
    $imageBitmap = New-Object System.Drawing.Bitmap($imageStream)
    $width = $imageBitmap.Width
    $height = $imageBitmap.Height
    $imageStream.Close()

    # Check if the image is larger than the specified dimensions
    if ($width -ge $MinWidth -and $height -ge $MinHeight) {
        Write-Host "Found large image: $($image.FullName)"
    }

    $processedImages++
    $progress = [math]::Round(($processedImages / $totalImages) * 100, 2)
    Write-Progress -Activity "Checking image sizes" -Status "Progress: $progress%" -PercentComplete $progress
}

Write-Progress -Activity "Checking image sizes" -Status "Progress: 100%" -PercentComplete 100
Write-Host "Image size check complete!"

 

Alle Bilder > 4K löschen
$SourceFolder = "C:\Path\to\SourceFolder"
$MinWidth = 3840
$MinHeight = 2160

# Get all image files in the source folder and its subfolders
$images = Get-ChildItem -Path $SourceFolder -Filter "*.jpg" -File -Recurse

$totalImages = $images.Count
$processedImages = 0

# Process each image file
foreach ($image in $images) {
    # Use .NET classes to read image dimensions
    $imageStream = New-Object System.IO.FileStream($image.FullName, [System.IO.FileMode]::Open)
    $imageBitmap = New-Object System.Drawing.Bitmap($imageStream)
    $width = $imageBitmap.Width
    $height = $imageBitmap.Height
    $imageStream.Close()

    # Check if the image is larger than the specified dimensions
    if ($width -ge $MinWidth -and $height -ge $MinHeight) {
        Write-Host "Deleting large image: $($image.FullName)"
        Remove-Item -Path $image.FullName -Force
    }

    $processedImages++
    $progress = [math]::Round(($processedImages / $totalImages) * 100, 2)
    Write-Progress -Activity "Checking and deleting large images" -Status "Progress: $progress%" -PercentComplete $progress
}

Write-Progress -Activity "Checking and deleting large images" -Status "Progress: 100%" -PercentComplete 100
Write-Host "Image size check and deletion complete!"