22import argparse
33import os
44
5- def count_valid_hosts_from_file (file_path ):
6- total_hosts = 0
5+ def extract_unique_hosts_from_file (file_path ):
6+ unique_hosts = set ()
77
88 try :
99 with open (file_path , 'r' ) as f :
@@ -18,36 +18,39 @@ def count_valid_hosts_from_file(file_path):
1818 network = ipaddress .ip_network (entry , strict = False )
1919 if isinstance (network , ipaddress .IPv4Network ):
2020 if network .prefixlen == 32 :
21- total_hosts += 1
21+ unique_hosts . add ( str ( network . network_address ))
2222 else :
23- num_hosts = max (network .num_addresses - 2 , 0 )
24- total_hosts += num_hosts
23+ # Add usable hosts only (skip network and broadcast)
24+ for host in network .hosts ():
25+ unique_hosts .add (str (host ))
2526 except ValueError as e :
2627 print (f"WARNING: { file_path } Line { line_number } - Invalid entry '{ entry } ': { e } " )
2728 except Exception as e :
2829 print (f"ERROR: Could not read file { file_path } : { e } " )
2930
30- return total_hosts
31+ return unique_hosts
3132
3233def main ():
33- parser = argparse .ArgumentParser (description = "Count valid hosts in a list of CIDRs or IPs." )
34+ parser = argparse .ArgumentParser (description = "Count unique valid hosts from CIDRs or IPs in files ." )
3435 parser .add_argument ("file" , nargs = '?' , help = "Path to file containing CIDR ranges or IPs, one per line." )
3536 parser .add_argument ("-d" , "--directory" , help = "Directory of files to process." )
3637 args = parser .parse_args ()
3738
3839 if args .directory :
39- grand_total = 0
40+ grand_total_hosts = set ()
4041 print (f"\n Processing directory: { args .directory } " )
4142 for entry in os .listdir (args .directory ):
4243 full_path = os .path .join (args .directory , entry )
4344 if os .path .isfile (full_path ):
44- count = count_valid_hosts_from_file (full_path )
45- print (f"{ entry } : { count } hosts" )
46- grand_total += count
47- print (f"\n Total hosts across all files: { grand_total } " )
45+ file_hosts = extract_unique_hosts_from_file (full_path )
46+ print (f"{ entry } : { len (file_hosts )} unique hosts" )
47+ grand_total_hosts .update (file_hosts )
48+ print (f"\n Total unique hosts across all files: { len (grand_total_hosts )} " )
49+
4850 elif args .file :
49- total = count_valid_hosts_from_file (args .file )
50- print (f"\n Total valid hosts in { args .file } (excluding network and broadcast, except for /32 IPs): { total } " )
51+ unique_hosts = extract_unique_hosts_from_file (args .file )
52+ print (f"\n Total unique hosts in { args .file } (excluding network and broadcast): { len (unique_hosts )} " )
53+
5154 else :
5255 print ("ERROR: Either a file or a directory must be specified." )
5356 parser .print_help ()
0 commit comments