11import argparse
22import sys
33
4- def wc (path , count_lines , count_words , count_bytes ):
5- """Count lines, words, and bytes for a single file."""
6- try :
7- with open (path , 'r' ) as f :
8- content = f .read ()
9-
10- lines = content .splitlines ()
11- words = content .split ()
12-
13- line_count = len (lines )
14- word_count = len (words )
15- byte_count = len (content .encode ('utf-8' ))
16-
17- if not any ([count_lines , count_words , count_bytes ]):
18- count_lines = True
19- count_words = True
20- count_bytes = True
214
22- parts = []
23-
24- if count_lines :
25- parts .append (str (line_count ))
26-
27- if count_words :
28- parts .append (str (word_count ))
29-
30- if count_bytes :
31- parts .append (str (byte_count ))
5+ def wc (path ):
6+ try :
7+ with open (path , "rb" ) as file :
8+ content = file .read ()
329
33- print (' ' .join (parts ), path )
10+ line_count = content .count (b"\n " )
11+ word_count = len (content .split ())
12+ byte_count = len (content )
3413
3514 return line_count , word_count , byte_count
3615
3716 except FileNotFoundError :
3817 print (
3918 f"wc: { path } : No such file or directory" ,
40- file = sys .stderr
19+ file = sys .stderr ,
4120 )
42- return (0 , 0 , 0 )
43-
4421 except IsADirectoryError :
4522 print (
4623 f"wc: { path } : Is a directory" ,
47- file = sys .stderr
24+ file = sys .stderr ,
25+ )
26+ except PermissionError :
27+ print (
28+ f"wc: { path } : Permission denied" ,
29+ file = sys .stderr ,
4830 )
49- return (0 , 0 , 0 )
31+ except OSError as error :
32+ print (
33+ f"wc: { path } : { error } " ,
34+ file = sys .stderr ,
35+ )
36+
37+ return None
38+
39+
40+ def print_stats (
41+ line_count ,
42+ word_count ,
43+ byte_count ,
44+ filename ,
45+ show_lines ,
46+ show_words ,
47+ show_bytes ,
48+ ):
49+ parts = []
50+
51+ if show_lines :
52+ parts .append (f"{ line_count :7d} " )
53+
54+ if show_words :
55+ parts .append (f"{ word_count :7d} " )
56+
57+ if show_bytes :
58+ parts .append (f"{ byte_count :7d} " )
59+
60+ print ("" .join (parts ), filename )
61+
5062
5163def main ():
52- parser = argparse .ArgumentParser ()
53- parser .add_argument ('-l' , action = 'store_true' , help = 'Count lines' )
54- parser .add_argument ('-w' , action = 'store_true' , help = 'Count words' )
55- parser .add_argument ('-c' , action = 'store_true' , help = 'Count bytes' )
56- parser .add_argument ('paths' , nargs = '+' , help = 'Files to count' )
64+ parser = argparse .ArgumentParser (
65+ description = "Print newline, word, and byte counts for files."
66+ )
67+
68+ parser .add_argument (
69+ "-l" ,
70+ action = "store_true" ,
71+ help = "print the newline count" ,
72+ )
73+
74+ parser .add_argument (
75+ "-w" ,
76+ action = "store_true" ,
77+ help = "print the word count" ,
78+ )
79+
80+ parser .add_argument (
81+ "-c" ,
82+ action = "store_true" ,
83+ help = "print the byte count" ,
84+ )
85+
86+ parser .add_argument (
87+ "paths" ,
88+ nargs = "+" ,
89+ help = "files to count" ,
90+ )
91+
5792 args = parser .parse_args ()
5893
94+ # If no options are supplied, wc prints all three counts.
95+ show_lines = args .l
96+ show_words = args .w
97+ show_bytes = args .c
98+
99+ if not any ((show_lines , show_words , show_bytes )):
100+ show_lines = True
101+ show_words = True
102+ show_bytes = True
103+
59104 total_lines = 0
60105 total_words = 0
61106 total_bytes = 0
62-
63- multiple_files = len (args .paths ) > 1
64- show_all = not any ([args .l , args .w , args .c ])
107+ successful_files = 0
65108
66109 for path in args .paths :
67- l , w , b = wc (path , args .l , args .w , args .c )
68- total_lines += l
69- total_words += w
70- total_bytes += b
71-
72- if multiple_files :
73- parts = []
74-
75- if args .l or show_all :
76- parts .append (str (total_lines ))
110+ counts = wc (path )
111+
112+ if counts is None :
113+ continue
114+
115+ line_count , word_count , byte_count = counts
116+
117+ total_lines += line_count
118+ total_words += word_count
119+ total_bytes += byte_count
120+ successful_files += 1
121+
122+ print_stats (
123+ line_count ,
124+ word_count ,
125+ byte_count ,
126+ path ,
127+ show_lines ,
128+ show_words ,
129+ show_bytes ,
130+ )
77131
78- if args .w or show_all :
79- parts .append (str (total_words ))
132+ if len (args .paths ) > 1 and successful_files > 0 :
133+ print_stats (
134+ total_lines ,
135+ total_words ,
136+ total_bytes ,
137+ "total" ,
138+ show_lines ,
139+ show_words ,
140+ show_bytes ,
141+ )
80142
81- if args .c or show_all :
82- parts .append (str (total_bytes ))
143+ return 0 if successful_files == len (args .paths ) else 1
83144
84- print (' ' .join (parts ), 'total' )
85145
86146if __name__ == "__main__" :
87- main ()
147+ sys . exit ( main () )
0 commit comments