#!/usr/bin/env python3 # # tee, but for pipes # # Example: # ./scripts/tee.py in_pipe out_pipe1 out_pipe2 # # Copyright (c) 2022, The littlefs authors. # SPDX-License-Identifier: BSD-3-Clause # import os import io import time import sys def openio(path, mode='r', buffering=-1): # allow '-' for stdin/stdout if path == '-': if mode == 'r': return os.fdopen(os.dup(sys.stdin.fileno()), mode, buffering) else: return os.fdopen(os.dup(sys.stdout.fileno()), mode, buffering) else: return open(path, mode, buffering) def main(in_path, out_paths, *, keep_open=False): out_pipes = [openio(p, 'wb', 0) for p in out_paths] try: with openio(in_path, 'rb', 0) as f: while True: buf = f.read(io.DEFAULT_BUFFER_SIZE) if not buf: if not keep_open: break # don't just flood reads time.sleep(0.1) continue for p in out_pipes: try: p.write(buf) except BrokenPipeError: pass except FileNotFoundError as e: print("error: file not found %r" % in_path) sys.exit(-1) except KeyboardInterrupt: pass if __name__ == "__main__": import sys import argparse parser = argparse.ArgumentParser( description="tee, but for pipes.", allow_abbrev=False) parser.add_argument( 'in_path', help="Path to read from.") parser.add_argument( 'out_paths', nargs='+', help="Path to write to.") parser.add_argument( '-k', '--keep-open', action='store_true', help="Reopen the pipe on EOF, useful when multiple " "processes are writing.") sys.exit(main(**{k: v for k, v in vars(parser.parse_intermixed_args()).items() if v is not None}))