81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
import argparse
|
|
import sys
|
|
|
|
from voussoirkit import betterhelp
|
|
from voussoirkit import interactive
|
|
from voussoirkit import pathclass
|
|
from voussoirkit import pipeable
|
|
from voussoirkit import vlogging
|
|
|
|
log = vlogging.getLogger(__name__, 'bitwise_or')
|
|
|
|
CHUNK_SIZE = 2**20
|
|
|
|
def bitwise_or_argparse(args):
|
|
patterns = pipeable.input_many(args.files, skip_blank=True, strip=True)
|
|
files = list(pathclass.glob_many_files(patterns))
|
|
|
|
if len(files) < 2:
|
|
log.fatal('Need at least two input files.')
|
|
return 1
|
|
|
|
output = pathclass.Path(args.output)
|
|
if output.is_dir:
|
|
log.fatal('Output path "%s" is a directory.', args.output)
|
|
return 1
|
|
|
|
if any(output == file for file in files):
|
|
log.fatal('Output cannot be one of the inputs.')
|
|
return 1
|
|
|
|
if not output.exists:
|
|
pass
|
|
elif args.overwrite:
|
|
pass
|
|
elif not pipeable.in_tty():
|
|
return 1
|
|
elif not interactive.getpermission(f'Overwrite "{output.absolute_path}"?'):
|
|
return 1
|
|
|
|
handles = [file.open('rb') for file in files]
|
|
output_handle = output.open('wb')
|
|
while True:
|
|
chunk = 0
|
|
length = 1
|
|
for handle in handles[:]:
|
|
read = handle.read(CHUNK_SIZE)
|
|
length = max(length, len(read))
|
|
if not read:
|
|
handles.remove(handle)
|
|
chunk |= int.from_bytes(read, 'big')
|
|
if not handles:
|
|
break
|
|
output_handle.write(chunk.to_bytes(length, 'big'))
|
|
pipeable.stdout(output.absolute_path)
|
|
|
|
@vlogging.main_decorator
|
|
def main(argv):
|
|
parser = argparse.ArgumentParser(
|
|
description='''
|
|
Merge two or more files by performing bitwise or on their bits.
|
|
That is, every byte of the output file will be the bitwise or of the
|
|
corresponding byte from all of the input files.
|
|
''',
|
|
)
|
|
|
|
parser.add_argument('files', nargs='+')
|
|
parser.add_argument('--output', required=True, type=pathclass.Path)
|
|
parser.add_argument(
|
|
'--overwrite',
|
|
action='store_true',
|
|
help='''
|
|
Provide this flag if the output file already exists and you'd like to
|
|
overwrite it.
|
|
''',
|
|
)
|
|
parser.set_defaults(func=bitwise_or_argparse)
|
|
|
|
return betterhelp.go(parser, argv)
|
|
|
|
if __name__ == '__main__':
|
|
raise SystemExit(main(sys.argv[1:]))
|