--- /dev/null
+#!/usr/bin/env python3
+# Written by Mike Frysinger <vapier@gmail.com>. Released into the public domain.
+
+"""Find long lines in text files."""
+
+import argparse
+from pathlib import Path
+import sys
+
+
+THIS_SCRIPT = Path(__file__).resolve()
+
+
+def get_parser() -> argparse.ArgumentParser:
+ """Get CLI parser."""
+ parser = argparse.ArgumentParser(description=__doc__)
+
+ # parser.add_argument("-c", "--count", action="store_true", help="Count how many lines match.")
+
+ parser.add_argument(
+ "--length", "--limit", default=80, type=int, help="Show lines longer than this."
+ )
+
+ parser.add_argument(
+ "-l",
+ "--list",
+ "--files-with-matches",
+ default=None,
+ action="store_true",
+ help="Print files that match.",
+ )
+ parser.add_argument(
+ "-L",
+ "--files-without-matches",
+ dest="list",
+ action="store_false",
+ help="Print files that do not match.",
+ )
+
+ parser.add_argument(
+ "-s",
+ "--with-size",
+ "--size",
+ default=False,
+ action="store_true",
+ help="Include line length.",
+ )
+ parser.add_argument(
+ "-S",
+ "--without-size",
+ dest="with_size",
+ action="store_false",
+ help="Do not include line length.",
+ )
+
+ parser.add_argument(
+ "-n",
+ "--line-number",
+ "--with-line-number",
+ dest="with_line_number",
+ default=True,
+ action="store_true",
+ help="Include line number.",
+ )
+ parser.add_argument(
+ "-N",
+ "--without-line-number",
+ dest="with_line_number",
+ action="store_false",
+ help="Do not include line number.",
+ )
+
+ parser.add_argument(
+ "--with-filename",
+ default=None,
+ action="store_true",
+ help="Prefix matches with the filename.",
+ )
+ parser.add_argument(
+ "-H",
+ "--without-filename",
+ dest="with_filename",
+ action="store_false",
+ help="Do not prefix matches with the filename.",
+ )
+
+ parser.add_argument("files", metavar="file", nargs="+", type=Path)
+ return parser
+
+
+def main(argv: list[str]) -> int | None:
+ """The main entry point for scripts."""
+ parser = get_parser()
+ opts = parser.parse_args(argv)
+ if opts.length < 0:
+ parser.error(f"--length={opts.length} may not be negative")
+
+ with_filename = opts.with_filename
+ if with_filename is None:
+ with_filename = len(opts.files) > 1
+
+ ret = 0
+ for file in opts.files:
+ pfx = f"{file}:" if with_filename else ""
+ try:
+
+ with file.open(encoding="utf-8") as fp:
+ for i, line in enumerate(fp, start=1):
+ line = line.rstrip("\n")
+ if len(line) > opts.length:
+ if opts.list is not None:
+ if opts.list:
+ print(file)
+ break
+
+ print(pfx, end="")
+ if opts.with_line_number:
+ print(f"{i}:", end="")
+ if opts.with_size:
+ print(f"{len(line)}:", end="")
+ print(line)
+ else:
+ if opts.list is False:
+ print(file)
+
+ except IOError as e:
+ print(f"{THIS_SCRIPT.name}: error: {file}: {e}", file=sys.stderr)
+ ret = 1
+
+ return ret
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))