read: add -c flag to copy bytes instead of lines

front
cinap_lenrek 2012-07-02 17:46:21 +02:00
parent 44f97f0cb1
commit bdb228e14a
2 changed files with 61 additions and 14 deletions

View File

@ -12,7 +12,10 @@ cat, read \- catenate files
.B -m .B -m
] [ ] [
.B -n .B -n
.I nline .I nlines
] [
.B -c
.I nbytes
] [ ] [
.I file ... .I file ...
] ]
@ -54,9 +57,21 @@ The
flag causes it to continue reading and writing multiple lines until end of file; flag causes it to continue reading and writing multiple lines until end of file;
.B -n .B -n
causes it to read no more than causes it to read no more than
.I nline .I nlines
lines. lines.
.PP .PP
With the
.B -c
flag,
.I read
copies exactly
.I nbytes
of characters instead of lines. It is mutually exclusive with
.B -n
and
.B -m
flag.
.PP
.I Read .I Read
always executes a single always executes a single
.B write .B write

View File

@ -3,6 +3,7 @@
int multi; int multi;
int nlines; int nlines;
vlong nchars;
char *status = nil; char *status = nil;
int int
@ -52,30 +53,61 @@ lines(int fd, char *file)
}while(multi || --nlines>0); }while(multi || --nlines>0);
} }
void
chars(int fd, char *file)
{
char buf[8*1024];
vlong m;
int n;
for(m = 0; m < nchars; m += n){
n = sizeof(buf);
if(n > (nchars - m))
n = nchars - m;
if((n = read(fd, buf, n)) < 0){
fprint(2, "read: error reading %s: %r\n", file);
exits("read error");
}
if(n == 0){
if(m == 0)
status = "eof";
break;
}
write(1, buf, n);
}
}
void
usage(void)
{
fprint(2, "usage: read [-m] [-n nlines] [-c nbytes] [files...]\n");
exits("usage");
}
void void
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
void (*proc)(int, char*);
int i, fd; int i, fd;
char *s;
proc = lines;
ARGBEGIN{ ARGBEGIN{
case 'c':
nchars = atoll(EARGF(usage()));
proc = chars;
break;
case 'n':
nlines = atoi(EARGF(usage()));
break;
case 'm': case 'm':
multi = 1; multi = 1;
break; break;
case 'n':
s = ARGF();
if(s){
nlines = atoi(s);
break;
}
/* fall through */
default: default:
fprint(2, "usage: read [-m] [-n nlines] [files...]\n"); usage();
exits("usage");
}ARGEND }ARGEND
if(argc == 0) if(argc == 0)
lines(0, "<stdin>"); (*proc)(0, "<stdin>");
else else
for(i=0; i<argc; i++){ for(i=0; i<argc; i++){
fd = open(argv[i], OREAD); fd = open(argv[i], OREAD);
@ -83,7 +115,7 @@ main(int argc, char *argv[])
fprint(2, "read: can't open %s: %r\n", argv[i]); fprint(2, "read: can't open %s: %r\n", argv[i]);
exits("open"); exits("open");
} }
lines(fd, argv[i]); (*proc)(fd, argv[i]);
close(fd); close(fd);
} }