Source code for xflow.utils.io
"""Input/Output utilities for file operations."""
import shutil
from pathlib import Path
from typing import List, Optional, Union
from .typing import PathLikeStr
[docs]
def copy_file(
source_path: PathLikeStr, target_path: PathLikeStr, filename: Optional[str] = None
) -> Path:
"""Copy a file to target directory.
Args:
source_path: Source file path
target_path: Target directory path
filename: Optional new filename (uses source filename if None)
Returns:
Path to the copied file
"""
source_path = Path(source_path)
target_path = Path(target_path)
target_path.mkdir(parents=True, exist_ok=True)
target_filename = filename or source_path.name
target_path = target_path / target_filename
shutil.copy2(source_path, target_path)
return target_path
def create_directory(path: PathLikeStr) -> Path:
"""Create directory if it doesn't exist.
Args:
path: Directory path to create
Returns:
Path to the created directory
"""
dir_path = Path(path)
dir_path.mkdir(parents=True, exist_ok=True)
return dir_path
[docs]
def scan_files(
root_paths: Union[PathLikeStr, List[PathLikeStr]],
extensions: Optional[Union[str, List[str]]] = None,
return_type: str = "path",
recursive: bool = True,
) -> Union[List[str], List[Path]]:
"""
Scan directories for files with specified extensions.
Args:
root_paths: Single path or list of paths to scan
extensions: File extensions to include (e.g., '.jpg' or ['.jpg', '.png']).
If None, includes all files.
return_type: "path" to return Path objects, "str" to return strings
recursive: Whether to scan subdirectories recursively
Returns:
Sorted list of file paths
"""
# Normalize inputs
if isinstance(root_paths, (str, Path)):
paths = [Path(root_paths)]
else:
paths = [Path(p) for p in root_paths]
if extensions is None:
ext_set = None
elif isinstance(extensions, str):
ext_set = {extensions.lower()}
else:
ext_set = {ext.lower() for ext in extensions}
# Collect files
file_paths = []
for root_path in paths:
if not root_path.exists():
continue
pattern = "**/*" if recursive else "*"
for file_path in root_path.glob(pattern):
if file_path.is_file():
if ext_set is None or file_path.suffix.lower() in ext_set:
if return_type in ["str", "string"]:
file_paths.append(str(file_path))
else:
file_paths.append(file_path)
return sorted(file_paths)