-
Notifications
You must be signed in to change notification settings - Fork 2
/
2cmd.py
128 lines (106 loc) · 5.03 KB
/
2cmd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import argparse
import signal
import os
from termcolor import colored
import time
import multiprocessing
def signal_handler(sig, frame):
sys.stderr.write("\nCtrl-C detected, terminating all workers...\n")
pool.terminate()
sys.exit(0)
def FileNameSan(sFileName):
sFileName = sFileName.replace("://", "-")
sFileName = sFileName.replace(":", "-")
sFileName = sFileName.replace("/", "-")
sFileName = sFileName.replace("&", "-")
sFileName = sFileName.replace("?", "-")
sFileName = sFileName.replace("*", "-")
# If a file name approaches the maximum length, tructate it and add a incrementing number:
if len(sFileName) > 240:
i = 1
sFileName = sFileName[:240]
while os.path.exists(sFileName + str(i)):
i += 1
sFileName = sFileName + str(i)
return sFileName
def escapeString(sString):
sString = sString.replace("$","\$", len(sString))
sString = sString.replace("&","\&", len(sString))
sString = sString.replace(";","\;", len(sString))
sString = sString.replace("\"","\\\"", len(sString))
#sString = sString.replace("","", len(sString))
return sString
def execCmd(sCmd):
if args.verbose:
sys.stderr.write((colored(sCmd,"green"))+"\n")
os.system(sCmd)
def getFullDir(sFile):
# if no path is provided, assume scriptdir/2cmd.xmpls:
if "/" in sFile:
sPathToFile = os.path.abspath(sFile)
else:
sPathToFile = os.path.dirname(os.path.realpath(sys.argv[0])) + "/2cmd.xmpls/" + sFile
return sPathToFile
signal.signal(signal.SIGINT, signal_handler)
# Get some commandline arguments:
parser = argparse.ArgumentParser(description="This script takes input lines from stdin and inserts them in the commands provided in the commands file. This way you can execute a certain command many times. For example you can take screen shots of URLs with cutycapt provided by output of another command.")
parser.add_argument("cmd", help="File containing one or more commands that should be executed. If no path is provided, a file in scriptdir/2cmd.xmpls is assumed. Use $2cmd$ or $2cmdsan$ in lowercase in each command line. $2cmd$ is replaced with each line from input. Use $cmdsan$ to sanitize a string for use in a filename.")
parser.add_argument("-hh", "--help2", help="Show the help inside the .2cmd script being called. Lines in the beginning of the script starting with # are displayed as help.", action="store_true")
parser.add_argument("-2", "--second", help="Pass a second variable to the script to run. This goes into variable $2nd$.")
parser.add_argument("-a", "--args", help="Provides cmdline arguments for the target program. Use double quotes to encloses spaces and other special characters.")
parser.add_argument("-t", "--timeout", help="Wait x milliseconds between commands.")
parser.add_argument("-v", "--verbose", help="In green, show the commands that are created from stdin and the provide config file.", action="store_true")
parser.add_argument("-w", "--workers", help="Defines how many worker threads execute the commands parallelly.", default=1)
args = parser.parse_args()
if not args.cmd:
parser.print_help(sys.stderr)
sys.exit(1)
try:
f = open(getFullDir(args.cmd), 'r')
aCmds = f.readlines()
f.close()
except FileNotFoundError:
print ("File " + getFullDir(args.cmd) + " not found, exiting...")
sys.exit(1)
iFirst = 0
pool = multiprocessing.Pool(int(args.workers))
boolOutsideHelp = False
boolHelpFound = False
boolNoHelpPrinted = False
for strInput in sys.stdin:
if args.timeout:
if iFirst == 1:
time.sleep (int(args.timeout)/1000)
iFirst = 1
for sCmd in aCmds:
sCmd = sCmd.strip()
if not strInput.strip():
continue
if args.help2:
if len(sCmd) > 0:
if sCmd[0] == "#" and boolOutsideHelp == False:
print (sCmd)
boolHelpFound = True
else:
boolOutsideHelp = True
if sCmd[0] != "#" and boolHelpFound == False and boolNoHelpPrinted == False:
print("No help comment found in " + getFullDir(args.cmd))
boolNoHelpPrinted = True
else:
if len(sCmd) > 0:
if sCmd[0] != "#":
strInputSan = FileNameSan(strInput)
sCmd = sCmd.replace("$2cmdsan$", strInputSan, len(sCmd))
if args.args:
sCmd = sCmd.replace("$args$", args.args, len(sCmd))
sCmd = sCmd.replace("$2cmd$", strInput, len(sCmd))
if args.second:
sCmd = sCmd.replace("$2nd$", args.second, len(sCmd))
sCmd = sCmd.replace("\n", "", len(sCmd))
sCmd = escapeString(sCmd)
pool.apply_async(execCmd, args = (sCmd, ))
pool.close()
pool.join()