#!/usr/bin/env python3 import io import sys import tarfile stdin = getattr(sys.stdin, 'buffer', sys.stdin) stdout = getattr(sys.stdout, 'buffer', sys.stdout) try: progname, old_shebang, new_shebang = sys.argv except ValueError: sys.exit("usage: replace-tarball-shebang '#!OLDSHEBANG' '#!NEWSHEBANG' < IN.tar[.gz] > OUT.tar") old_shebang_bytes = old_shebang.encode() new_shebang_bytes = new_shebang.encode() with tarfile.open(fileobj=stdin, mode='r|*') as in_tar, \ tarfile.open(fileobj=stdout, mode='w', format=tarfile.PAX_FORMAT, pax_headers=in_tar.pax_headers) as out_tar: for info in in_tar: if info.isfile(): file = in_tar.extractfile(info) assert(file is not None) # this assert convinces mypy that it's okay to do file.read() data = file.read() if data.startswith(old_shebang_bytes + b' ') or data.startswith(old_shebang_bytes + b'\n'): print('editing', info.name, file=sys.stderr) assert info.size == len(data) data = new_shebang_bytes + data[len(old_shebang_bytes):] info.size = len(data) out_tar.addfile(info, io.BytesIO(data)) else: out_tar.addfile(info)