@@ -432,8 +432,13 @@ def _argument_parser():
432432 dest = "compress" ,
433433 const = False ,
434434 help = "Decompress the file instead of compressing." )
435- parser .add_argument ("-c" , "--stdout" , action = "store_true" ,
436- help = "write on standard output" )
435+ output_group = parser .add_mutually_exclusive_group ()
436+ output_group .add_argument ("-c" , "--stdout" , action = "store_true" ,
437+ help = "write on standard output" )
438+ output_group .add_argument ("-o" , "--output" ,
439+ help = "Write to this output file" )
440+ parser .add_argument ("-f" , "--force" , action = "store_true" ,
441+ help = "Overwrite output without prompting" )
437442 # -b flag not taken by either gzip or igzip. Hidden attribute. Above 32K
438443 # diminishing returns hit. _compression.BUFFER_SIZE = 8k. But 32K is about
439444 # ~6% faster.
@@ -448,31 +453,46 @@ def main():
448453
449454 compresslevel = args .compresslevel or _COMPRESS_LEVEL_TRADEOFF
450455
451- # Determine input file
452- if args .compress and args .file is None :
453- in_file = sys .stdin .buffer
454- elif args .compress and args .file is not None :
455- in_file = io .open (args .file , mode = "rb" )
456- elif not args .compress and args .file is None :
457- in_file = IGzipFile (mode = "rb" , fileobj = sys .stdin .buffer )
458- elif not args .compress and args .file is not None :
459- base , extension = os .path .splitext (args .file )
460- if extension != ".gz" and not args .stdout :
461- sys .exit (f"filename doesn't end in .gz: { args .file !r} . "
462- f"Cannot determine output filename." )
463- in_file = open (args .file , "rb" )
464-
465- # Determine output file
466- if args .compress and (args .file is None or args .stdout ):
467- out_file = IGzipFile (mode = "wb" , compresslevel = compresslevel ,
468- fileobj = sys .stdout .buffer )
469- elif args .compress and args .file is not None :
470- out_file = open (args .file + ".gz" , mode = "wb" ,
471- compresslevel = compresslevel )
472- elif not args .compress and (args .file is None or args .stdout ):
473- out_file = sys .stdout .buffer
474- elif not args .compress and args .file is not None :
475- out_file = io .open (base , "wb" )
456+ if args .output :
457+ out_filepath = args .output
458+ elif args .stdout :
459+ out_filepath = None # to stdout
460+ elif args .file is None :
461+ out_filepath = None # to stout
462+ else :
463+ if args .compress :
464+ out_filepath = args .file + ".gz"
465+ else :
466+ out_filepath , extension = os .path .splitext (args .file )
467+ if extension != ".gz" and not args .stdout :
468+ sys .exit (f"filename doesn't end in .gz: { args .file !r} . "
469+ f"Cannot determine output filename." )
470+ if out_filepath is not None and not args .force :
471+ if os .path .exists (out_filepath ):
472+ yes_or_no = input (f"{ out_filepath } already exists; "
473+ f"do you wish to overwrite (y/n)?" )
474+ if yes_or_no not in {"y" , "Y" , "yes" }:
475+ sys .exit ("not overwritten" )
476+
477+ if args .compress :
478+ if args .file is None :
479+ in_file = sys .stdin .buffer
480+ else :
481+ in_file = io .open (args .file , mode = "rb" )
482+ if out_filepath is not None :
483+ out_file = open (out_filepath , "wb" , compresslevel = compresslevel )
484+ else :
485+ out_file = IGzipFile (mode = "wb" , fileobj = sys .stdout .buffer ,
486+ compresslevel = compresslevel )
487+ else :
488+ if args .file :
489+ in_file = open (args .file , mode = "rb" )
490+ else :
491+ in_file = IGzipFile (mode = "rb" , fileobj = sys .stdin .buffer )
492+ if out_filepath is not None :
493+ out_file = io .open (out_filepath , mode = "wb" )
494+ else :
495+ out_file = sys .stdout .buffer
476496
477497 global READ_BUFFER_SIZE
478498 READ_BUFFER_SIZE = args .buffer_size
0 commit comments