One of the most useful commands when i used DOS, was deltree
. Quickly and easy, deleting large areas of the hard disk, with no point of return... In Linux, there isn't such a command, or perhaps, it's a bit disguised, but never the less, it hasn't the features of the original deltree
command or the one, we have here.
The script it self is nothing much. Make sure to have installed the tqdm
module, as it's used for the progress bar display.
You have the following options to use:
usage: deltree [-h] [-s] [-y] [-c] [-q] directory
Delete a directory and all its contents. Use -h or --help for help.
positional arguments:
directory The path of the directory to delete
options:
-h, --help show this help message and exit
-s, --simulate Simulate deletion by listing files instead of deleting them
-y, --yes Disable confirmation prompt and delete without asking
-q, --quiet Suppress information output
As you see, there is also a simulate option, which will not delete any files, but it will show you a list of the directories/files, that are going to be deleted and a total summary of size and number of dirs/files, that would be deleted. The program will ask you once for confirmation and then start the process of deletion, showing a simple "linux-like" progress bar.
The program, may be simple but for sure can be developed more and add more features. For example one could implement an except switch to not delete certain files/dirs or add a protection of removing file while having sudo privileges or protection from removing files/dir, from the root directory etc.
Just copy/paste and make it executable:
#!/usr/bin/python3
import os
import argparse
from tqdm import tqdm
VERSION="1.0.0"
NAME="Deltree"
QUIET=False
def qprint(s,quiet=False):
global QUIET
if QUIET: return
print(s)
def format_size(size_bytes):
"""Convert a size in bytes to a more readable format (KB, MB, GB)."""
if size_bytes < 1024:
return f"{size_bytes} bytes"
elif size_bytes < 1024**2:
return f"{size_bytes / 1024:.2f} KB"
elif size_bytes < 1024**3:
return f"{size_bytes / 1024**2:.2f} MB"
else:
return f"{size_bytes / 1024**3:.2f} GB"
def delete_directory(dir_path, simulate=False, force=False):
"""Delete a directory and all its contents or list them if simulate is True."""
if os.path.exists(dir_path):
if simulate:
qprint(f'Simulating deletion of directory: {dir_path}')
total_files = 0
total_dirs = 0
total_size = 0
for root, dirs, files in os.walk(dir_path):
level = root.replace(dir_path, '').count(os.sep)
indent = ' ' * 4 * (level)
print(f'{indent}{os.path.basename(root)}/')
subindent = ' ' * 4 * (level + 1)
for f in files:
file_path = os.path.join(root, f)
file_size = os.path.getsize(file_path)
total_size += file_size
total_files += 1
print(f'{subindent}{f}')
total_dirs += len(dirs)
# Display totals
qprint(f'\n Total directories: {total_dirs:,.0f}')
qprint(f' Total files: {total_files:,.0f}')
qprint(f' Total size of files: {format_size(total_size)} / {total_size} bytes\n')
else:
if not force:
confirmation = input(f'Delete directory "{dir_path}" and all its contents? (yes/no): ')
if confirmation.lower() == 'yes' or confirmation.lower() == 'y':
print("")
else:
qprint('Deletion canceled.')
return
# Count total files and directories for progress bar
total_items = sum(len(files) + len(dirs) for _, dirs, files in os.walk(dir_path))
total_files = 0
total_dirs = 0
total_size = 0
with tqdm(total=total_items, desc='Deleting items', unit='item') as pbar:
for root, dirs, files in os.walk(dir_path, topdown=False):
for name in files:
file_path = os.path.join(root, name)
total_size += os.path.getsize(file_path) # Accumulate file size
total_files += 1 # Count files
os.remove(file_path)
pbar.update(1)
for name in dirs:
total_dirs += 1 # Count directories
os.rmdir(os.path.join(root, name))
pbar.update(1)
os.rmdir(dir_path) # Finally remove the root directory
qprint(f'\nDirectory {dir_path} and all its contents have been deleted.')
qprint(f'\n Total files: {total_files}')
qprint(f' Total directories: {total_dirs}')
qprint(f' Total size of files: {format_size(total_size)} / {total_size} bytes\n')
else:
qprint(f'Directory {dir_path} does not exist.')
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Delete a directory and all its contents. Use -h or --help for help.')
parser.add_argument('directory', type=str, help='The path of the directory to delete')
parser.add_argument('-s', '--simulate', action='store_true', help='Simulate deletion by listing files instead of deleting them')
parser.add_argument('-y', '--yes', action='store_true', help='Disable confirmation prompt and delete without asking')
parser.add_argument('-q', '--quiet', action='store_true', help='Suppress information output')
args = parser.parse_args()
QUIET = args.quiet
qprint(f"{NAME} v{VERSION}")
delete_directory(args.directory, simulate=args.simulate, force=args.yes)