Python Random Password Generator

A simple python script to put in the system $PATH. Uses argparse to handle script arguments and secret to randomize the characters. I use this to generate both usernames and password, often when setting up a bunch of test accounts. Example to generate 5 passwords with a length of 21 characters and not using symbols. generate-password.py -l 21 -c 5 #!/usr/bin/env python3 import argparse import secrets import string def parse_arguments() -> argparse.Namespace: """Use argparse to get script arguments.""" parser = argparse.ArgumentParser() parser.add_argument("-l", "--length", help="Password length", type=int, default=16) parser.add_argument("-c", "--count", help="Number of passwords", type=int, default=1) parser.add_argument("-s", "--symbols", help="Include symbols", action="store_true") return parser.parse_args() def generate_password(length: int, *, symbols: bool) -> str: """Generate and return random password string.""" characters = string.ascii_letters + string.digits if symbols: characters += string.punctuation return "".join(secrets.choice(characters) for i in range(length)) def main() -> None: """System main loop.""" args = parse_arguments() for _i in range(args.count): password = generate_password(args.length, symbols=args.symbols) print(password) if __name__ == "__main__": main()

November 26, 2025

Python Directory File Sorter

A script I wrote to sort my ~/Downloads/ directory content into different file extensions category directories. It’s constantly a work in process and a way I use to test different technologies and features of new python versions. I’ve taken inspiration from so many different scripts and projects so it’s hard to write them all. #!/usr/bin/env python3 import argparse import logging import sys from pathlib import Path categories = { "Images": {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".heic"}, "3D Printing": {".stl", ".gcode", ".3mf", ".f3d", ".stp"}, "Documents": { ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".csv", ".rtf", ".odt", ".pages", ".key", ".md", ".opml", ".tex", ".bib", ".odp", }, "Executables": { ".exe", ".msi", ".bat", ".sh", ".dmg", ".app", ".deb", ".rpm", ".apk", ".jar", ".pkg", ".xpi", ".appimage", }, "Compressed": {".zip", ".rar", ".tar", ".gz", ".7z"}, "Videos": {".mp4", ".mov", ".wmv", ".flv", ".avi", ".mkv", ".webm", ".mpg", ".mpeg", ".3gp"}, "Audio": {".mp3", ".wav", ".aac", ".ogg", ".flac", ".m4a", ".wma"}, "Code": { ".py", ".ipynb", ".java", ".cpp", ".c", ".h", ".cs", ".xml", ".json", ".yaml", ".yml", ".sql", ".rb", ".pl", ".cmd", ".ps1", ".dockerfile", ".fig", ".js", ".html", ".css", ".php", ".sqlite", ".db", }, "Others": {".kdbx"}, } def get_config() -> argparse.Namespace: """Use argparse to get configuration.""" parser = argparse.ArgumentParser( prog="directory-file-sorter.py", formatter_class=argparse.ArgumentDefaultsHelpFormatter, description="Sort directory files into category directories.", ) parser.add_argument( "-v", "--verbose", action="count", dest="verbosity", default=0, help="verbose output (repeat for increased verbosity)", ) parser.add_argument( "-q", "--quiet", action="store_const", const=-1, default=0, dest="verbosity", help="quiet output (show errors only)", ) parser.add_argument( dest="directory", type=lambda p: Path(p).absolute(), ) return parser.parse_args() def setup_logging(verbosity: int) -> None: """Setups logging with the correct verbosity level.""" base_loglevel = 20 verbosity = min(verbosity, 2) loglevel = base_loglevel - (verbosity * 10) logging.basicConfig(level=loglevel, format="%(message)s") def create_destination_directories(base_path: Path) -> None: """Create all the sort destination directories.""" logger = logging.getLogger(__name__) for category in categories: category_directory = base_path / category if not category_directory.exists(): category_directory.mkdir() logger.info("Created category directory %s.", category_directory) def get_file_category(file_extension: str) -> str: """Return category for specified extension.""" for category, extensions in categories.items(): if file_extension.lower() in extensions: return category return "Others" def move_file(src_path: Path, dest_directory: Path) -> None: """Move file into destination directory.""" logger = logging.getLogger(__name__) dest_path = dest_directory / src_path.name counter = 1 while dest_path.exists(): dest_path = dest_directory / f"{src_path.stem}_{counter}{src_path.suffix}" counter += 1 logger.debug("Moving to %s.", dest_path) src_path.rename(dest_path) def main() -> None: """System main loop.""" conf = get_config() setup_logging(conf.verbosity) logger = logging.getLogger(__name__) if not conf.directory.exists(): logger.critical("Directory %s does not exist.", conf.directory) sys.exit(1) create_destination_directories(conf.directory) for file in conf.directory.iterdir(): if file.is_file(): logger.debug("Handling file %s.", file) category = get_file_category(file.suffix) logger.debug("Categoried as %s.", category) move_file(file, conf.directory / category) if __name__ == "__main__": main()

November 25, 2025

GoAccess - Web Log Analyzer

GoAccess is an open source real-time web log analyzer I have been using this application for years to analyze log files from apache web server.

October 30, 2025

watch - Repeat Command Every nth Second

Repeat a command every nth second and show output. watch free -m Default interval is 2 seconds but can be changed with -n, --interval. watch --interval 10 free -m

October 30, 2025

git - Change Previous Commit

Don’t amend public commits Add staged changes to previous commit With no message change. git commit --amend --no-edit Changing the message. git commit --amend -m "an updated commit message" If you wish to open the editor for message. git commit --amend Running the last two with no staged changes will only edit the message.

October 26, 2025

sed - Remove Comment Lines

Removes comments # (results in empty lines) and empty lines from file in place. sed -i -e 's/#.*$//' -e '/^$/d' fileName Example Strips php.ini of all comments and all empty lines, perfect for diffing. sed -i -e 's/;.*$//' -e '/^$/d' php.ini

October 25, 2025