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

This commit is contained in:
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 -n
.I nline
.I nlines
] [
.B -c
.I nbytes
] [
.I file ...
]
@ -54,9 +57,21 @@ The
flag causes it to continue reading and writing multiple lines until end of file;
.B -n
causes it to read no more than
.I nline
.I nlines
lines.
.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
always executes a single
.B write

View file

@ -3,6 +3,7 @@
int multi;
int nlines;
vlong nchars;
char *status = nil;
int
@ -52,30 +53,61 @@ lines(int fd, char *file)
}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
main(int argc, char *argv[])
{
void (*proc)(int, char*);
int i, fd;
char *s;
proc = lines;
ARGBEGIN{
case 'c':
nchars = atoll(EARGF(usage()));
proc = chars;
break;
case 'n':
nlines = atoi(EARGF(usage()));
break;
case 'm':
multi = 1;
break;
case 'n':
s = ARGF();
if(s){
nlines = atoi(s);
break;
}
/* fall through */
default:
fprint(2, "usage: read [-m] [-n nlines] [files...]\n");
exits("usage");
usage();
}ARGEND
if(argc == 0)
lines(0, "<stdin>");
(*proc)(0, "<stdin>");
else
for(i=0; i<argc; i++){
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]);
exits("open");
}
lines(fd, argv[i]);
(*proc)(fd, argv[i]);
close(fd);
}