Source code for filesystem.directory

"""
# Directory

---

## Overview
The Directory module is a component of the FileSystemPro library that provides a collection of functions
for handling directory-related operations. It simplifies tasks such as path manipulation, 
directory creation and deletion, and file retrieval within directories.

## Features
- `Path Combination:` Dynamically combines multiple paths into a single path string.
- `Directory Creation:` Creates new directories, with an option to create necessary subdirectories.
- `Directory Deletion:` Deletes directories, with an option for recursive deletion.
- `Directory Existence Check:` Checks whether a directory exists at a specified path.
- `File Retrieval:` Retrieves a list of files within a directory using glob patterns.
- `Parent Directory Information:` Retrieves the name or path of a file's parent directory.
- `Directory Listing:` Lists all subdirectories within a given directory.
- `Directory Renaming:` Renames a directory if it exists.

## Detailed Functionality
The module's functions are designed to be intuitive and provide a high level of abstraction from the
underlying file system operations.

### Path Combination (`combine`)
The `combine` function takes multiple path segments and intelligently combines them into a single path. 
It ensures that the resulting path is valid and absolute, 
raising an error if the initial segment is not an absolute path.

### Directory Creation and Deletion (`create`, `delete`)
The `create` function allows for the creation of directories, 
with the option to create all necessary subdirectories if they do not exist. 
The `delete` function removes directories, with the ability to recursively delete all contents if specified.

### Directory and File Information (`exists`, `get_files`, `get_parent_name`, `get_parent`, `get_name`)
The `exists` function checks for the existence of a directory. 
The `get_files` function uses glob patterns to retrieve files within a directory. 
The `get_parent_name`, `get_parent`, and `get_name` functions provide information 
about the parent directory of a given path.

### Directory Operations (`join`, `list`, `rename`)
The `join` function is a versatile path joiner that can handle multiple path segments. 
The `list` function returns a list of all subdirectories within a specified directory. 
The `rename` function allows for renaming a directory, 
ensuring that the operation only occurs if the directory exists.

## Usage
To use the functions provided by this module, 
import the module and call the desired function with the appropriate parameters:

```python
from filesystem import directory as dir
```
"""

import os
import shutil
import filesystem as fs
from filesystem import wrapper as wra

[docs]def combine(*args, paths=[]): """ # directory.combine(*args, paths=[]) --- ### Overview Combines a list of paths or arguments into a single path. If the first argument or the first element in the paths list is not an absolute path, it raises a ValueError. ### Parameters: *args (str): The paths to combine. The first argument must be an absolute path. paths (list): A list of paths to combine. The first element in the list must be an absolute path. Defaults to an empty list. ### Returns: str: The combined path. ### Raises: - ValueError: If the first argument or the first element in the paths list is not an absolute path. ### Examples: - Combines all paths in the list, starting with an absolute path. ```python combine(paths=["/home/user/directory", "subdirectory", "file.txt"]) ``` - Combines all arguments, starting with an absolute path. ```python combine("/home/user/directory", "subdirectory", "file.txt") ``` """ if paths: result = paths[0] if not os.path.isabs(result): raise ValueError( f'''Invalid argument: The path "{result}" is not an absolute path. - The first argument inside paths list must to be an absolute path. For example, "/home/user/directory" is a valid absolute path. Please provide a valid absolute path. ''' ) for path in paths: if os.path.isabs(path): result = path else: result = join(result, path) return result result = args[0] if not os.path.isabs(result): raise ValueError( f'''Invalid argument: The path "{result}" is not an absolute path. - The first argument must to be an absolute path. For example, "/home/user/directory" is a valid absolute path. Please provide a valid absolute path. ''' ) for path in args[1:]: if path == '': continue if os.path.isabs(path): result = path else: if not result.endswith(os.sep): result += os.sep result += path return result
[docs]def create(path, create_subdirs=True): """ # directory.create(path, create_subdirs=True) --- ### Overview Creates a directory at the specified path. If `create_subdirs` is True, all intermediate-level directories needed to contain the leaf directory will be created. After the directory is created, it returns the details of the created directory. ### Parameters: path (str): The directory path to create. create_subdirs (bool): A flag that indicates whether to create intermediate subdirectories. Defaults to True. ### Returns: dict: A dictionary containing the details of the created directory. ### Raises: - FileExistsError: If the directory already exists when `create_subdirs` is False. - PermissionError: If the permission is denied. - FileNotFoundError: If the path does not exist. ### Examples: - Creates all intermediate subdirectories if they don't exist and returns their details. ```python create("/path/to/directory") ``` - Creates only the leaf directory, raises an error if any intermediate directory doesn't exist, and returns the details of the created directory. ```python create("/path/to/directory", False) ``` """ if create_subdirs: os.makedirs(path, exist_ok=True) else: os.mkdir(path) return wra.get_object(path)
[docs]def delete(path, recursive=False): """ # directory.delete(path, recursive=False) --- ### Overview Deletes a directory at the specified path. If `recursive` is True, the directory and all its contents will be removed. ### Parameters: path (str): The directory path to delete. recursive (bool): A flag that indicates whether to delete the directory even if it is not empty. Defaults to False. ### Returns: None ### Raises: - Exception: If the directory does not exist or if the directory is not empty and `recursive` is False. ### Examples: - Deletes an empty directory. ```python delete("/path/to/directory") ``` - Deletes a directory and all its contents. ```python delete("/path/to/directory", True) ``` """ if not exists(path): raise Exception(f'\n\n>> The directory "{path}" does not exist.') if not os.listdir(path) or recursive: shutil.rmtree(path) else: raise Exception(f'\n\n>> The directory "{path}" is not empty.\n>> Use delete(path, True) to remove anyway.')
[docs]def exists(path): """ # directory.exists(path) --- ### Overview Checks if a directory exists at the specified path. ### Parameters: path (str): The directory path to check. ### Returns: bool: True if the directory exists, False otherwise. ### Examples: - Checks if a directory exists. ```python exists("/path/to/directory") ``` """ if os.path.isdir(path): return True return False
[docs]def get_directories(path, fullpath=True): """ # directory.get_directories(path, fullpath=True) --- ### Overview Retrieves a list of directories within the specified path. ### Parameters: path (str): The directory path to search within. fullpath (bool, optional): If True, returns the full path of each directory. Defaults to True. ### Returns: list: A list of directory names or full paths, depending on the `fullpath` parameter. ### Raises: - FileNotFoundError: If the specified path does not exist. - PermissionError: If the permission is denied to access the path. ### Examples: - Retrieves directory names within a specified path. ```python get_directories("/path/to/directory") ``` - Retrieves full paths of directories within a specified path. ```python get_directories("/path/to/directory", fullpath=True) ``` """ directory_list = [] for dir in os.listdir(path): if os.path.isdir(join(path, dir)): if fullpath == True: directory_list.append(f'{path}{fs.OS_SEPARATOR}{dir}') else: directory_list.append(dir) return directory_list
[docs]def get_name(path): """ # directory.get_name(path) --- ### Overview Retrieves the name of the directory of the specified path. If the path has an extension, it is assumed to be a file, and the parent directory name is returned. If the path does not have an extension, it is assumed to be a directory, and the directory name is returned. ### Parameters: path (str): The directory or file path from which to retrieve the name. ### Returns: str: The name of the parent directory or the file. ### Examples: - Retrieves the parent directory name when the path is a file. ```python get_name("/path/to/directory/file.txt") ``` - Retrieves the directory name when the path is a directory. ```python get_name("/path/to/directory") ``` """ if wra.has_extension(path): return f'{get_parent_name(path)}' else: return os.path.basename(os.path.dirname(path + '/'))
[docs]def get_parent(path): """ # directory.get_parent(path) --- ### Overview Retrieves the parent directory from the specified path. ### Parameters: path (str): The directory path from which to retrieve the parent directory. ### Returns: str: The parent directory of the specified path. ### Examples: - Retrieves the parent directory when the path ends with a slash. ```python get_parent("/path/to/directory/") ``` - Retrieves the parent directory when the path does not end with a slash. ```python get_parent("/path/to/directory") ``` """ return os.path.dirname(path)
[docs]def get_parent_name(path): """ # directory.get_parent_name(path) --- ### Overview Retrieves the parent directory name from the specified path. ### Parameters: path (str): The directory path from which to retrieve the parent directory name. ### Returns: str: The name of the parent directory. ### Examples: - Retrieves the parent directory name when the path ends with a slash. ```python get_parent_name("/path/to/directory/") ``` - Retrieves the parent directory name when the path does not end with a slash. ```python get_parent_name("/path/to/directory") ``` """ if path.endswith('/'): path = path[:-1] return os.path.basename(path) return os.path.basename(os.path.dirname(path))
[docs]def get_size(directory_path): """ # directory.get_size(directory_path) --- ### Overview Calculates the total size of all files in the specified directory. The size is returned in bytes, KB, MB, GB, or TB, depending on the total size. ### Parameters: - directory_path (str): The path of the directory to calculate the size of. ### Returns: - str: A string representing the total size of the directory, formatted as a float followed by the unit of measurement. ### Raises: - FileNotFoundError: If the directory does not exist. - PermissionError: If permission is denied. ### Examples: - Calculate the total size of all files in a directory: ```python get_size("/path/to/directory") """ if not os.path.isdir(directory_path): raise FileNotFoundError(f"O diretório '{directory_path}' não foi encontrado.") total_size = sum( os.path.getsize(os.path.join(dirpath, filename)) for dirpath, dirnames, filenames in os.walk(directory_path) for filename in filenames ) for unit in ['bytes', 'KB', 'MB', 'GB', 'TB']: if total_size < 1024.0: return f"{total_size:3.1f} {unit}" total_size /= 1024.0
[docs]def join(path1='', path2='', path3='', path4='', paths=[]): """ # directory.join(path1='', path2='', path3='', path4='', paths=[]) --- ### Overview Joins multiple directory paths into a single path. The function ensures that each directory path ends with a separator before joining. If a directory path does not end with a separator, one is added. ### Parameters: path1, path2, path3, path4 (str): The directory paths to join. Defaults to an empty string. paths (list): A list of additional directory paths to join. Defaults to an empty list. ### Returns: str: The joined directory path. ### Examples: - Joins multiple directory paths. ```python join("/path/to", "directory", paths=["subdirectory", "file.txt"]) ``` - Joins multiple directory paths without additional paths. ```python join("/path/to", "directory") ``` """ key_dir = "" if not path1.endswith(os.sep): if path1 != "": path1 = path1 + os.sep key_dir += path1 if not path2.endswith(os.sep): if path2 != "": path2 = path2 + os.sep key_dir += path2 if not path3.endswith(os.sep): if path3 != "": path3 = path3 + os.sep key_dir += path3 if not path4.endswith(os.sep): if path4 != "": path4 = path4 + os.sep key_dir += path4 if paths: for item in paths: if not item.endswith(os.sep): item = item + os.sep key_dir += item return key_dir[:-1]
[docs]def move(source, destination, move_root=True): """ # directory.move(source, destination, move_root=True) --- ### Overview The move function is designed to move files or directories from a source location to a destination. It provides flexibility by allowing you to specify whether intermediate-level subdirectories should be created during the move operation. ### Parameters: source (str): The path to the file or directory you want to move. destination (str): The target location where the source should be moved. move_root (bool, optional): A flag indicating whether to move the entire directory (including its root) or just its contents. Defaults to True. ### Returns: None ### Raises: - FileNotFoundError: If the source path does not exist. - PermissionError: If permission is denied during the move operation. ### Examples: - Move the entire directory (including intermediate subdirectories): ```python move("/path/to/source", "/path/to/destination") ``` - Move only the leaf directory (raise an error if intermediate directories don't exist): ```python move("/path/to/source", "/path/to/destination", move_root=False) ``` """ if exists(destination): if move_root: shutil.move(source, destination) else: entries = os.listdir(source) for root, dirs, files in os.walk(source): for d in dirs: shutil.move(os.path.join(root, d), os.path.join(destination, d)) for f in files: shutil.move(os.path.join(root, f), os.path.join(destination, f)) else: if move_root: create(destination) shutil.move(source, destination) else: entries = os.listdir(source) for root, dirs, files in os.walk(source): for d in dirs: shutil.move(os.path.join(root, d), os.path.join(destination, d)) for f in files: shutil.move(os.path.join(root, f), os.path.join(destination, f))
[docs]def rename(old_path, new_path): """ # directory.rename(old_path, new_path) --- ### Overview Renames a directory from the old directory path to the new directory path. If the old directory path does not exist or is not a directory, the function returns False. ### Parameters: old_path (str): The old directory path to rename. new_path (str): The new directory path. ### Returns: bool: True if the directory was successfully renamed, False otherwise. ### Examples: - Renames a directory. ```python rename("/path/to/old_directory", "/path/to/new_directory") ``` """ if os.path.isdir(old_path): os.rename(old_path, new_path) return True return False