#!/usr/bin/env python3 """\ List all those script files that have executable bits and require shebang or have shebang and require executable bits. Usage: findnoshebang.py file-or-dir1 [file-or-dir2...] """ __author__ = 'Serhiy Storchaka' import os import re import stat import sys suffixes = ('.py', '.pyw', '.sh') shebang = b'#!' execmode = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH is_text = re.compile(b'^[\t\n\v\f\r -\xff]+$').match is_ignored_dir = re.compile(r'^\..+|^CVS$').match def walk_scripts(paths): for path in paths: if os.path.isfile(path): yield path elif os.path.isdir(path): for root, dirs, files in os.walk(path): if is_ignored_dir(os.path.basename(root)): del dirs[:] continue for filename in files: yield os.path.join(root, filename) if __name__ == "__main__": for path in walk_scripts(sys.argv[1:]): try: mode = os.stat(path).st_mode with open(path, 'rb') as f: data = f.read(512) except OSError: pass hasshebang = data.startswith(shebang) if mode & execmode: if not hasshebang and is_text(data): print('x', path) pass else: if hasshebang and path.endswith(suffixes): print('-', path)