Rename

Renames a file or folder to a specified new name while keeping it in the same directory.

Rename


Processing

Renames a file or folder to a specified new name while keeping it in the same directory. Handles conflicts based on the chosen conflict mode (skip, overwrite, or auto-number).

Inputs

current_path
The path to the file or folder to be renamed.
new name
The new name for the file or folder. For files, this excludes the extension, which is preserved from the original file.

Inputs Types

Input Types
current_path Str, Path
new name Str

You can check the list of supported types here: Available Type Hints.

Outputs

status
A boolean indicating whether the rename operation was successful.
final path
The resulting path of the file or folder after renaming.

Outputs Types

Output Types
status Bool
final path Str

You can check the list of supported types here: Available Type Hints.

Options

The Rename brick contains some changeable options:

Manage Conflict By
Specifies how to handle naming conflicts. Options are "skip" (do not rename if target exists), "auto-number" (append a number to the name), or "overwrite" (replace the existing file or folder).
Verbose
Enables detailed logging of the rename operation when set to True.
import logging
from coded_flows.types import Str, Tuple, Union, Bool, Path

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def rename(
    current_path: Union[Str, Path], new_name: Str, options=None
) -> Tuple[Bool, Str]:
    brick_display_name = "Rename"
    options = options or {}
    verbose = options.get("verbose", True)
    conflict_mode = options.get("conflict_mode", "skip")
    final_path = str(current_path)
    status = False
    try:
        current_path_obj = Path(current_path)
        if verbose:
            logger.info(f"[{brick_display_name}] Starting rename operation")
            logger.info(f"[{brick_display_name}] Current path: {current_path_obj}")
            logger.info(f"[{brick_display_name}] New name: {new_name}")
            logger.info(f"[{brick_display_name}] Conflict mode: {conflict_mode}")
        if not current_path_obj.exists():
            verbose and logger.error(
                f"[{brick_display_name}] Source path does not exist: '{current_path_obj}'."
            )
            raise ValueError(f"Source path does not exist: {current_path_obj}")
        invalid_chars = '<>:"/\\|?*'
        if any((char in new_name for char in invalid_chars)):
            verbose and logger.error(
                f"[{brick_display_name}] Invalid characters in new name: '{new_name}'."
            )
            raise ValueError(f"Invalid characters in new name: '{new_name}'")
        if not new_name.strip():
            verbose and logger.error(f"[{brick_display_name}] New name cannot be empty")
            raise ValueError("New name cannot be empty")
        parent_dir = current_path_obj.parent
        if current_path_obj.is_file():
            original_extension = current_path_obj.suffix
            if "." in new_name:
                new_name_without_ext = new_name.rsplit(".", 1)[0]
            else:
                new_name_without_ext = new_name
            final_new_name = new_name_without_ext + original_extension
        else:
            final_new_name = new_name
        new_path = parent_dir / final_new_name
        verbose and logger.info(f"[{brick_display_name}] Target path: {new_path}")
        if new_path.exists() and new_path != current_path_obj:
            verbose and logger.info(
                f"[{brick_display_name}] Target path already exists"
            )
            if conflict_mode == "skip":
                verbose and logger.info(
                    f"[{brick_display_name}] Skipping rename due to existing target"
                )
            elif conflict_mode == "overwrite":
                verbose and logger.info(
                    f"[{brick_display_name}] Removing existing target for overwrite"
                )
                try:
                    if new_path.is_dir():
                        import shutil

                        shutil.rmtree(new_path)
                    else:
                        new_path.unlink()
                    status = True
                except Exception as e:
                    verbose and logger.error(
                        f"[{brick_display_name}] Failed to remove existing target."
                    )
                    raise Exception(f"Failed to remove existing target: {e}")
            elif conflict_mode == "auto-number":
                verbose and logger.info(
                    f"[{brick_display_name}] Finding available name with auto-numbering."
                )
                if current_path_obj.is_file():
                    name_part = new_name_without_ext
                    ext_part = original_extension
                elif "." in final_new_name:
                    (name_part, ext_part) = final_new_name.rsplit(".", 1)
                    ext_part = "." + ext_part
                else:
                    name_part = final_new_name
                    ext_part = ""
                counter = 1
                while new_path.exists():
                    numbered_name = f"{name_part}_{counter}{ext_part}"
                    new_path = parent_dir / numbered_name
                    counter += 1
                    if counter > 9999:
                        if verbose:
                            logger.error(
                                f"[{brick_display_name}] Too many numbered variations exist!"
                            )
                        raise Exception("Too many numbered variations exist!")
                verbose and logger.info(
                    f"[{brick_display_name}] Using auto-numbered name: {new_path.name}."
                )
                status = True
        if new_path == current_path_obj:
            verbose and logger.info(
                f"[{brick_display_name}] Source and target are the same, no operation needed."
            )
            final_path = str(new_path)
            status = True
        verbose and logger.info(f"[{brick_display_name}] Performing rename operation.")
        current_path_obj.rename(new_path)
        final_path = str(new_path)
        if verbose:
            logger.info(
                f"[{brick_display_name}] Rename operation completed successfully"
            )
            logger.info(f"[{brick_display_name}] Final path: '{final_path}'.")
    except Exception as e:
        verbose and logger.error(f"[{brick_display_name}] Unexpected error!")
        raise
    return (status, final_path)

Brick Info

version v0.1.4
python 3.10, 3.11, 3.12, 3.13
requirements
    -