tools

various tools I have been using throughout the years
Log | Files | Refs | README | LICENSE

commit 7e27284ae5e454afdfe484a1da5c491c5214fcf9
parent bccd2a000cccad112dd2bf9d43fb36702492ede1
Author: mtmn <miro@haravara.org>
Date:   Thu,  2 Jul 2026 00:45:58 +0200

diggah: add port to ssh connection

Diffstat:
Mdiggah/diggah.py | 30+++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/diggah/diggah.py b/diggah/diggah.py @@ -98,6 +98,7 @@ class RemoteExecutor: start_dt: datetime | None, end_dt: datetime | None, include_files: bool, + port: int | None = None, ) -> Iterable[str]: """ Executes a find command on the remote host and yields the results. @@ -107,6 +108,14 @@ class RemoteExecutor: if "@" in host_str: username, hostname = host_str.split("@", 1) + if ":" in hostname: + host_part, _, port_part = hostname.rpartition(":") + if not port_part.isdigit(): + raise ValueError(f"invalid port '{port_part}' in host '{host_str}'") + hostname = host_part + if port is None: + port = int(port_part) + # Load SSH config ssh_config = paramiko.SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") @@ -122,7 +131,8 @@ class RemoteExecutor: if username is None and "user" in user_config: username = user_config["user"] - port = int(user_config.get("port", 22)) + if port is None: + port = int(user_config.get("port", 22)) key_filename = user_config.get("identityfile") cmd_parts = ["find", path] @@ -198,6 +208,7 @@ class Diggah: path: str = ".", dry_run: bool = False, host: str | None = None, + port: int | None = None, relative: bool = False, output: str | bool = False, ): @@ -215,7 +226,10 @@ class Diggah: all: If True, show all finds regardless of time. path: Directory to search in (default: "."). dry_run: If True, print calculated dates and exit. - host: SSH host to run the command on (e.g., user@example.com). + host: SSH host to run the command on (e.g., user@example.com + or user@example.com:2222). + port: SSH port for the remote host (overrides host:port and + ssh config; default 22). relative: If True, output paths relative to the search root. output: If True or a path, write output to file(s) instead of stdout. If a path is provided, writes to that file. @@ -234,10 +248,12 @@ class Diggah: for start_dt, end_dt, outfile in ranges: if dry_run: self._print_dry_run( - start_dt, end_dt, path, files, host, relative, output, outfile + start_dt, end_dt, path, files, host, port, relative, output, outfile ) else: - self._run_search(start_dt, end_dt, path, files, host, relative, outfile) + self._run_search( + start_dt, end_dt, path, files, host, port, relative, outfile + ) def _determine_search_ranges( self, @@ -332,6 +348,7 @@ class Diggah: path: str, include_files: bool, host: str | None, + port: int | None, relative: bool, output: str | bool, outfile: str | None, @@ -342,6 +359,8 @@ class Diggah: print(f"Include Files: {include_files}") if host: print(f"Host: {host}") + if port: + print(f"Port: {port}") print("Mode: Remote (find command)") else: print("Mode: Local (python walk)") @@ -357,13 +376,14 @@ class Diggah: path: str, include_files: bool, host: str | None, + port: int | None, relative: bool, outfile: str | None, ): results: Iterable[str] if host: results = RemoteExecutor().execute( - host, path, start_dt, end_dt, include_files + host, path, start_dt, end_dt, include_files, port ) else: start_ts = start_dt.timestamp() if start_dt else None