Skip to content

Instantly share code, notes, and snippets.

@phagenlocher
Created April 19, 2018 07:48
Show Gist options
  • Select an option

  • Save phagenlocher/e9f22264e78905de35e9295e47a02972 to your computer and use it in GitHub Desktop.

Select an option

Save phagenlocher/e9f22264e78905de35e9295e47a02972 to your computer and use it in GitHub Desktop.
Run any command recursively
#!/usr/bin/python3
import os
import re
import argparse
import subprocess
from functools import reduce
def run_cmd(path, cmd, verbose):
for i, el in enumerate(cmd):
if '@' == el:
cmd[i] = path
if '@' in el:
cmd[i] = el.replace('@', os.path.abspath(path))
if verbose:
print('[!]', ' '.join(cmd))
subprocess.run(cmd)
def walk(start, cmd, verbose, fregex, pregex, nohidden):
if len(cmd) == 0:
cmd = None
if not cmd is None:
if not reduce(lambda x,y: x or y, map(lambda x : '@' in x, cmd)):
cmd.append('@')
if nohidden:
fregex = '^[^.]' + fregex
pregex = '^[^.]' + pregex
frx = re.compile(fregex)
prx = re.compile(pregex)
for root, dirs, files in os.walk(start):
root = os.path.abspath(root)
if verbose:
print('[*] Visiting',root)
for d in dirs.copy():
if not prx.match(d):
dirs.remove(d)
for f in files:
if frx.match(f):
path = os.path.join(root, f)
if cmd is None:
print(path)
else:
run_cmd(path, cmd.copy(), verbose)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Execute a command for all files')
parser.add_argument('-p', '--path', default='.', help="The path to search all files on")
parser.add_argument('-fr', '--file-regex', default='.+', help="A regular expression to match files to")
parser.add_argument('-pr', '--path-regex', default='.+', help="A regular expression to match paths to")
parser.add_argument('--nohidden', action='store_true', help="Hidden files and hidden directories will not be visited")
parser.add_argument('-v', '--verbose', action='store_true', help="Have more output")
parser.add_argument('command', default=None, nargs=argparse.REMAINDER, help="The command to run on all the valid files (if none is supplied all files get listed). An @ can be used as a placeholder for the file (if not supplied the filename will be appended to the command)")
args = vars(parser.parse_args())
walk(args['path'], args['command'], args['verbose'], args['file_regex'], args['path_regex'], args['nohidden'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment