Repository navigation
Implement ls and wc command line tools in Python
#18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| """List directory entries, one per line.""" | ||
|
|
||
| import argparse | ||
| from pathlib import Path | ||
| import sys | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument("-1", action="store_true", help="print one entry per line") | ||
| parser.add_argument("-a", "--all", action="store_true", help="include hidden entries") | ||
| parser.add_argument("directory", nargs="?", default=".") | ||
| args = parser.parse_args() | ||
|
|
||
| try: | ||
| entries = sorted(Path(args.directory).iterdir(), key=lambda entry: entry.name) | ||
| for entry in entries: | ||
| if args.all or not entry.name.startswith("."): | ||
| print(entry.name) | ||
| except OSError as error: | ||
| print(f"ls: {error}", file=sys.stderr) | ||
| return 1 | ||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| """Count lines, words, and bytes in files.""" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In Concretely:
So as a reader (or user of this script), you’d believe You might find it useful to ask yourself: if someone else tried to reuse To "like" or "dislike" this comment, please follow this link |
||
|
|
||
| import argparse | ||
| from pathlib import Path | ||
| import sys | ||
|
|
||
|
|
||
| def count_file(filename): | ||
| text = Path(filename).read_bytes().decode("utf-8") | ||
| return len(text.splitlines()), len(text.split()), len(text) | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument("-l", action="store_true", help="print line counts") | ||
| parser.add_argument("-w", action="store_true", help="print word counts") | ||
| parser.add_argument("-c", action="store_true", help="print byte counts") | ||
| parser.add_argument("files", nargs="+") | ||
| args = parser.parse_args() | ||
| selected = [args.l, args.w, args.c] | ||
| if not any(selected): | ||
| selected = [True, True, True] | ||
|
|
||
| def print_counts(counts, label): | ||
| values = [str(value) for value, enabled in zip(counts, selected) if enabled] | ||
| print(" ".join([*values, label])) | ||
|
Comment on lines
+24
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inside
Since Would an inlined version still feel readable to you, or does having To "like" or "dislike" this comment, please follow this link |
||
|
|
||
| totals = [0, 0, 0] | ||
| successful = 0 | ||
| status = 0 | ||
| for filename in args.files: | ||
| try: | ||
| counts = count_file(filename) | ||
| except (OSError, UnicodeError) as error: | ||
| print(f"wc: {filename}: {error}", file=sys.stderr) | ||
| status = 1 | ||
| continue | ||
| print_counts(counts, filename) | ||
| totals = [total + value for total, value in zip(totals, counts)] | ||
| successful += 1 | ||
| if successful > 1: | ||
| print_counts(totals, "total") | ||
| return status | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In
main, theentriesvariable is created only to be used immediately in theforloop:entries = sorted(Path(args.directory).iterdir(), key=lambda entry: entry.name)for entry in entries:Because
entriesisn’t reused elsewhere, one question to consider is whether introducing this temporary name actually helps readability for you, or whether you’d find it just as clear to loop directly over the sorted iterator. When a variable is introduced and only used once right away, it can sometimes add a tiny bit of cognitive overhead for readers who then need to remember thatentriesis simply the sorted directory listing.How do you feel about the clarity here? If you find that the name
entriesmeaningfully improves understanding, it can be worth keeping. If not, you might explore iterating directly over the sorted result to reduce the number of moving parts in the function.To "like" or "dislike" this comment, please follow this link