there is some problens with non-latin filenames

If you're encountering issues with non-Latin filenames, you can try using the os.path.normpath function to normalize the file paths before copying. This function converts slashes to the appropriate type for the current operating system and can help resolve issues with filenames containing characters from different encodings.

Here's an updated version of the script with this change:

import bpy
import os
import shutil

# Initialize an empty list to store file paths
file_paths = []

# Iterate over all objects in the scene
for obj in bpy.data.objects:
    # Check if the object has a material
    if obj.material_slots:
        # Iterate over all materials assigned to the object
        for material_slot in obj.material_slots:
            # Check if the material has a node tree
            if material_slot.material.node_tree:
                # Check if the material uses a texture
                for node in material_slot.material.node_tree.nodes:
                    if node.type == "TEX_IMAGE" and node.image:
                        # Get the file path of the image and add it to the list
                        file_path = node.image.filepath
                        file_paths.append(file_path)

# Iterate over all scenes in the blend file
for scene in bpy.data.scenes:
    # Check if the scene has a linked library
    if scene.library:
        # Get the file path of the linked library and add it to the list
        file_path = scene.library.filepath
        file_paths.append(file_path)

# Iterate over all Alembic cache files in the blend file
for cache_file in bpy.data.cache_files:
    # Get the file path of the Alembic cache file and add it to the list
    file_path = cache_file.filepath
    file_paths.append(file_path)

# Get the blend file's directory
blend_dir = os.path.dirname(bpy.data.filepath)

# Create the assets folder in the blend file's directory
assets_dir = os.path.join(blend_dir, "assets")
os.makedirs(assets_dir, exist_ok=True)

# Copy each file in file_paths to the assets folder
num_files = 0
for file_path in file_paths:
    # Normalize the file path
    file_path = os.path.normpath(file_path)
    
    # Get the destination file path
    dest_path = os.path.join(assets_dir, os.path.basename(file_path))
    
    # Copy the file
    shutil.copy2(file_path, dest_path)
    num_files += 1

# Print the report to the console
print("Copied", num_files, "files from the following locations:")
for file_path in file_paths:
    print("-", file_path)

This script should now correctly handle non-Latin filenames when copying the files to the assets folder.

OSError: [Errno 22] Invalid argument

This error is likely being caused by an invalid file path, such as a file path that contains characters that are not supported by your operating system's file system.

You can try using the os.path.realpath function to get the real file path of the file, which will resolve any symbolic links or relative file paths to an absolute file path that is guaranteed to be valid on your operating system.

Here's an updated version of the script that uses os.path.realpath:


import bpy
import os
import shutil

# Initialize an empty list to store file paths
file_paths = []

# Iterate over all objects in the scene
for obj in bpy.data.objects:
    # Check if the object has a material
    if obj.material_slots:
        # Iterate over all materials assigned to the object
        for material_slot in obj.material_slots:
            # Check if the material has a node tree
            if material_slot.material.node_tree:
                # Check if the material uses a texture
                for node in material_slot.material.node_tree.nodes:
                    if node.type == "TEX_IMAGE" and node.image:
                        # Get the file path of the image and add it to the list
                        file_path = node.image.filepath
                        file_paths.append(file_path)

# Iterate over all scenes in the blend file
for scene in bpy.data.scenes:
    # Check if the scene has a linked library
    if scene.library:
        # Get the file path of the linked library and add it to the list
        file_path = scene.library.filepath
        file_paths.append(file_path)

# Iterate over all Alembic cache files in the blend file
for cache_file in bpy.data.cache_files:
    # Get the file path of the Alembic cache file and add it to the list
    file_path = cache_file.filepath
    file_paths.append(file_path)

# Get the blend file's directory
blend_dir = os.path.dirname(bpy.data.filepath)

# Create the assets folder in the blend file's directory
assets_dir = os.path.join(blend_dir, "assets")
os.makedirs(assets_dir, exist_ok=True)

# Copy each file in file_paths to the assets folder
num_files = 0
for file_path in file_paths:
    # Get the real file path
    file_path = os.path.realpath(file_path)
    
    # Get the destination file path
    dest_path = os.path.join(assets_dir, os.path.basename(file_path))
    
    # Copy the file
    shutil.copy2(file_path, dest_path)
    num_files += 1

# Print the report to the console
print("Copied", num_files, "files from the following locations:")
for file_path in file_paths:
    print("-", file_path)

This script should resolve any issues with invalid file paths and copy the files to the assets folder successfully.

unite duplicate file paths

You can use a set to keep track of unique file paths. The set will automatically eliminate duplicates, so you don't need to manually check if a file path has already been added to the list.

Here's the updated script:

import bpy
import os
import shutil

# Initialize an empty set to store unique file paths
file_paths = set()

# Iterate over all objects in the scene
for obj in bpy.data.objects:
    # Check if the object has a material
    if obj.material_slots:
        # Iterate over all materials assigned to the object
        for material_slot in obj.material_slots:
            # Check if the material has a node tree
            if material_slot.material.node_tree:
                # Check if the material uses a texture
                for node in material_slot.material.node_tree.nodes:
                    if node.type == "TEX_IMAGE" and node.image:
                        # Get the file path of the image and add it to the set
                        file_path = node.image.filepath
                        file_paths.add(file_path)

# Iterate over all scenes in the blend file
for scene in bpy.data.scenes:
    # Check if the scene has a linked library
    if scene.library:
        # Get the file path of the linked library and add it to the set
        file_path = scene.library.filepath
        file_paths.add(file_path)

# Iterate over all Alembic cache files in the blend file
for cache_file in bpy.data.cache_files:
    # Get the file path of the Alembic cache file and add it to the set
    file_path = cache_file.filepath
    file_paths.add(file_path)

# Get the blend file's directory
blend_dir = os.path.dirname(bpy.data.filepath)

# Create the assets folder in the blend file's directory
assets_dir = os.path.join(blend_dir, "assets")
os.makedirs(assets_dir, exist_ok=True)

# Copy each file in file_paths to the assets folder
num_files = 0
for file_path in file_paths:
    # Get the real file path
    file_path = os.path.realpath(file_path)
    
    # Get the destination file path
    dest_path = os.path.join(assets_dir, os.path.basename(file_path))
    
    # Copy the file
    shutil.copy2(file_path, dest_path)
    num_files += 1

# Print the report to the console
print("Copied", num_files, "files from the following locations:")
for file_path in file_paths:
    print("-", file_path)

This script will copy each unique file path only once to the assets folder.