"head", a complement to tail(1)
Richard O'Keefe
ok at edai.UUCP
Tue Mar 6 11:58:12 AEST 1984
----
head is a command for getting prefixes of files.
cat >head.1 <<'EOF'
.TH HEAD 1 Edinburgh
.SH NAME
head \- deliver the first part of a file
.SH SYNOPSIS
.B head
[-\fBh\fR] [-number[\fBbclp\fR]] [file]...
.SH DESCRIPTION
.I Head
copies the first part of each of the named files to the standard output.
If no file is named, the standard input is used.
.PP
Copying continues for
.I number
units from the beginning, where a unit is
.B (b)
a block of 512 characters,
.B (c)
a character,
.B (l)
a line (terminated by and including a LineFeed), or
.B (p)
a page (terminated by and including a FormFeed).
.PP
If no unit is given, the default is Lines.
If no number is given, the default is 10.
If neither a number nor a unit is given, the hyphen should be omitted
as well, as a single hyphen is accepted as a file name signifying the
standard input.
.PP
You may have more than one -number-unit specification. Each applies
to all the files to its right until the next one.
The default for an omitted number or unit is "same as last time".
.PP
If the \fBh\fR flag is given, each file's prefix will be preceded
by a newline, the file's name, a colon, and a newline. A common
use for -h is to skim several files, and it helps to see which is which.
This flag may only given when units=line or pages.
.SH EXAMPLES
Copy the first 10 lines of the standard input:
.PP
head
.PP
Copy the first page of each C file in this directory:
.PP
head -1p *.c
.PP
Copy the first 2 lines of a, the first 5 lines of b and c, all
of d, and the first 4 lines of e:
.PP
head -2 a -5 b c -1000b d -4l e
.PP
Check the first 10 lines of each Pascal file, but as there are
lots of them, ask to be reminded which is which:
.PP
head -h *.p
.SH "SEE ALSO"
tail(1)
.SH DIAGNOSTICS
.I head
will complain if it can't open a file, if you try to read the standard
input twice, or if you give an invalid unit specification. Only in the
last case will it stop at once. The return code is 0 if all went well,
1 if there was an error.
'EOF'
cat >head.c <<'EOF'
/*% cc -n -s -O % -o head
head [-number[blpc]] file... [-number[blpc]] file... ...
Copies an initial segment of each named file in turn to the standard
output. If no file is specified, the standard input is used. The
standard input may also be specified by the "file" `-'.
The size of the initial segment is the given number (default 10) of
Characters (c)
Blocks (b) which are taken to be 512 characters long
Lines (l) which terminate at and including LineFeeds
Pages (p) which terminate at and including FormFeeds
If no unit is specified, the first length specifier will default to
lines and remaining specifiers to the same unit as the previous one.
For example, head -2b foo -3 baz
will copy three blocks from baz, not three lines.
*/
#define Chars 1 /* characters per unit */
#define Blocks 512 /* characters per unit */
#define Lines 10 /* unit's terminating character (LF) */
#define Pages 12 /* unit's terminating character (FF) */
#define None 0 /* no file processed yet */
#define StdIn 2 /* stdin has been read */
#define Other 1 /* some other file has been read */
void do_file(fd, number, units)
int fd; /* UNIX file descriptor */
long number; /* how many units to copy */
int units; /* what sort of units to copy */
{
char buffer[4096]; /* input buffer */
long nread;
if (units == Lines || units == Pages) {
while ((nread = read(fd, buffer, sizeof buffer)) > 0) {
register char *p = buffer;
register int n = nread;
while (--n >= 0)
if (*p++ == units && --number == 0) {
write(1, buffer, nread - n);
return;
}
write(1, buffer, nread);
}
} else {
/* units == Chars || units == Blocks */
number *= units;
while ((nread = read(fd, buffer, sizeof buffer)) > 0) {
if (nread <= number) {
write(1, buffer, nread);
number -= nread;
} else {
write(1, buffer, number);
return;
}
}
}
}
void main(argc, argv)
int argc;
char **argv;
{
long number = 10; /* number of units to copy */
int units = Lines; /* what sort of units to copy */
int readin = None; /* what files have we read */
int haderr = 0; /* did we have to miss a file? */
int header = 0; /* was the -h flag given? */
while (--argc > 0) {
if (**++argv != '-') {
int fd = open(*argv, 0);
if (fd < 0) {
write(2, "head: ", 6);
perror(*argv);
haderr = 1;
} else {
if (header) printf("%s:\n", *argv);
do_file(fd, number, units);
close(fd);
}
readin |= Other;
} else
if (argv[0][1] == '\0') {
if (readin & StdIn) {
static char gripe[] = "head: can't read stdin twice\n";
write(2, gripe, sizeof gripe);
haderr = 1;
} else {
if (header) write(1, "-:\n", 4);
do_file(0, number, units);
readin |= StdIn;
}
} else {
register char *s = *argv + 1;
register int n = 0;
while (*s >= '0' && *s <= '9') n *= 10, n += *s++ - '0';
if (n != 0) number = n;
switch (*s|32) {
case 'h': header = 1; break;
case 'n': header = 0; break;
case 'b': units = Blocks; break;
case 'c': units = Chars; break;
case 'l': units = Lines; break;
case 'p': units = Pages; break;
case ' ' : /* no change */ break;
default : {
static char gripe[] = "head: units are C,B,L,or P\n";
write(2, gripe, sizeof gripe);
exit(1);
}
}
if (header && units != Lines && units != Pages) {
static char gripe[] = "head: -h requires -l or -p\n";
write(2, gripe, sizeof gripe);
header = 0, haderr = 1;
}
}
}
if (readin == None) do_file(0, number, units);
exit(haderr);
}
'EOF'
I hope you find this as useful as I do.
More information about the Comp.sources.unix
mailing list