77 lines
1.9 KiB
Python
Executable File
77 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# ollie:parallel read
|
|
# ollie:tier cold
|
|
# description: Read a file with accurate line numbers. Prefer segments (start/end) over full-file reads.
|
|
# Args: <file_path> [start] [end] [--head=<n>]
|
|
|
|
import sys
|
|
import os
|
|
from itertools import islice
|
|
|
|
MAX_LINES = 500 # default window for whole-file reads (no start/end)
|
|
MAX_SEGMENT = 2000 # max window when start/end are given
|
|
MAX_LINE_LEN = 2000
|
|
|
|
# Parse --head=N from args
|
|
head = None
|
|
args = []
|
|
for a in sys.argv[1:]:
|
|
if a.startswith('--head='):
|
|
head = int(a.split('=', 1)[1])
|
|
else:
|
|
args.append(a)
|
|
|
|
if not args:
|
|
print("usage: file_read <file_path> [start] [end] [--head=N]")
|
|
sys.exit(1)
|
|
|
|
file_path = args[0]
|
|
start = int(args[1]) if len(args) > 1 else 1
|
|
end = int(args[2]) if len(args) > 2 else None
|
|
|
|
if not os.path.isabs(file_path):
|
|
print(f"error: path must be absolute, got: {file_path}")
|
|
sys.exit(1)
|
|
|
|
if not os.path.exists(file_path):
|
|
print("(new file)")
|
|
sys.exit(0)
|
|
|
|
if not os.path.isfile(file_path):
|
|
print(f"error: not a regular file: {file_path}")
|
|
sys.exit(1)
|
|
|
|
with open(file_path, 'rb') as f:
|
|
if b'\x00' in f.read(8192):
|
|
print("(binary file)")
|
|
sys.exit(0)
|
|
|
|
start = max(1, start)
|
|
if head:
|
|
end = start + head - 1
|
|
elif end is None:
|
|
end = start + MAX_LINES - 1
|
|
else:
|
|
end = min(end, start + MAX_SEGMENT - 1)
|
|
|
|
with open(file_path, 'r', errors='replace') as f:
|
|
# Skip lines before start
|
|
for _ in islice(f, start - 1):
|
|
pass
|
|
# Read only the lines we need
|
|
segment_lines = list(islice(f, end - start + 1))
|
|
|
|
if not segment_lines:
|
|
print("(empty file)" if start == 1 else "(no lines in range)")
|
|
sys.exit(0)
|
|
|
|
out = []
|
|
for i, line in enumerate(segment_lines):
|
|
lineno = start + i
|
|
text = line.rstrip('\n')
|
|
if len(text) > MAX_LINE_LEN:
|
|
text = text[:MAX_LINE_LEN] + '...'
|
|
out.append(f"{lineno:>6}\t{text}")
|
|
|
|
print('\n'.join(out))
|