| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- #!/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}))
|