diff options
| author | Xin LI <delphij@FreeBSD.org> | 2022-07-13 04:14:25 +0000 |
|---|---|---|
| committer | Xin LI <delphij@FreeBSD.org> | 2022-07-13 04:14:25 +0000 |
| commit | 643ac419fafba89f5adda0e0ea75b538727453fb (patch) | |
| tree | 2ce7e4cd870fecdad6036f3804b89d3ffbb6c441 /usr.bin/head | |
| parent | d8cce8145c39812cc31b50070c44d66ca21a5127 (diff) | |
Diffstat (limited to 'usr.bin/head')
| -rw-r--r-- | usr.bin/head/Makefile | 1 | ||||
| -rw-r--r-- | usr.bin/head/head.1 | 24 | ||||
| -rw-r--r-- | usr.bin/head/head.c | 33 | ||||
| -rwxr-xr-x | usr.bin/head/tests/head_test.sh | 45 |
4 files changed, 90 insertions, 13 deletions
diff --git a/usr.bin/head/Makefile b/usr.bin/head/Makefile index b966f8165795..0c9056924969 100644 --- a/usr.bin/head/Makefile +++ b/usr.bin/head/Makefile @@ -4,6 +4,7 @@ .include <src.opts.mk> PROG= head +LIBADD= util HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/usr.bin/head/head.1 b/usr.bin/head/head.1 index c74983822916..3968e7283b17 100644 --- a/usr.bin/head/head.1 +++ b/usr.bin/head/head.1 @@ -28,7 +28,7 @@ .\" @(#)head.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd April 10, 2018 +.Dd June 12, 2022 .Dt HEAD 1 .Os .Sh NAME @@ -36,6 +36,7 @@ .Nd display first lines of a file .Sh SYNOPSIS .Nm +.Op Fl qv .Op Fl n Ar count | Fl c Ar bytes .Op Ar .Sh DESCRIPTION @@ -59,14 +60,30 @@ of each of the specified files. Print .Ar count lines of each of the specified files. +.Pp +Both +.Ar count +and +.Ar bytes +may also be specified with size suffixes supported by +.Xr expand_number 3 . +.It Fl q , Fl -quiet , Fl -silent +Suppresses printing of headers when multiple files are being examined. +.It Fl v , Fl -verbose +Prepend each file with a header. .El .Pp -If more than a single file is specified, each file is preceded by a +If more than a single file is specified, or if the +.Fl v +option is used, each file is preceded by a header consisting of the string .Dq ==> XXX <== where .Dq XXX is the name of the file. +The +.Fl q +flag disables the printing of the header in all cases. .Sh EXIT STATUS .Ex -std .Sh EXAMPLES @@ -83,7 +100,8 @@ in the following way to, for example, display only line 500 from the file .Pp .Dl $ head -n 500 foo | tail -n 1 .Sh SEE ALSO -.Xr tail 1 +.Xr tail 1 , +.Xr expand_number 3 .Sh HISTORY The .Nm diff --git a/usr.bin/head/head.c b/usr.bin/head/head.c index 0226dd96d9a6..1c6368823e7c 100644 --- a/usr.bin/head/head.c +++ b/usr.bin/head/head.c @@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> +#include <libutil.h> + #include <libcasper.h> #include <casper/cap_fileargs.h> @@ -66,7 +68,7 @@ __FBSDID("$FreeBSD$"); * Bill Joy UCB August 24, 1977 */ -static void head(FILE *, int); +static void head(FILE *, intmax_t); static void head_bytes(FILE *, off_t); static void obsolete(char *[]); static void usage(void); @@ -75,6 +77,9 @@ static const struct option long_opts[] = { {"bytes", required_argument, NULL, 'c'}, {"lines", required_argument, NULL, 'n'}, + {"quiet", no_argument, NULL, 'q'}, + {"silent", no_argument, NULL, 'q'}, + {"verbose", no_argument, NULL, 'v'}, {NULL, no_argument, NULL, 0} }; @@ -82,29 +87,37 @@ int main(int argc, char *argv[]) { FILE *fp; - char *ep; off_t bytecnt; - int ch, first, linecnt, eval; + intmax_t linecnt; + int ch, first, eval; fileargs_t *fa; cap_rights_t rights; + int qflag = 0; + int vflag = 0; linecnt = -1; eval = 0; bytecnt = -1; obsolete(argv); - while ((ch = getopt_long(argc, argv, "+n:c:", long_opts, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "+n:c:qv", long_opts, NULL)) != -1) { switch(ch) { case 'c': - bytecnt = strtoimax(optarg, &ep, 10); - if (*ep || bytecnt <= 0) + if (expand_number(optarg, &bytecnt) || bytecnt <= 0) errx(1, "illegal byte count -- %s", optarg); break; case 'n': - linecnt = strtol(optarg, &ep, 10); - if (*ep || linecnt <= 0) + if (expand_number(optarg, &linecnt) || linecnt <= 0) errx(1, "illegal line count -- %s", optarg); break; + case 'q': + qflag = 1; + vflag = 0; + break; + case 'v': + qflag = 0; + vflag = 1; + break; case '?': default: usage(); @@ -134,7 +147,7 @@ main(int argc, char *argv[]) eval = 1; continue; } - if (argc > 1) { + if (vflag || (qflag == 0 && argc > 1)) { (void)printf("%s==> %s <==\n", first ? "" : "\n", *argv); first = 0; @@ -155,7 +168,7 @@ main(int argc, char *argv[]) } static void -head(FILE *fp, int cnt) +head(FILE *fp, intmax_t cnt) { char *cp; size_t error, readlen; diff --git a/usr.bin/head/tests/head_test.sh b/usr.bin/head/tests/head_test.sh index 1fc3cb10b455..9d1b97507c12 100755 --- a/usr.bin/head/tests/head_test.sh +++ b/usr.bin/head/tests/head_test.sh @@ -119,6 +119,48 @@ read_from_stdin_body() { atf_check cmp outfile expectfile } +atf_test_case silent_header +silent_header_head() { + atf_set "descr" "Test head(1)'s silent header feature" +} +silent_header_body() { + #head(1) defaults to head -n 10 if no args are given. + jot 11 1 11 > file1 + jot 11 2 12 > file2 + jot 10 1 10 > expectfile + jot 10 2 11 >> expectfile + head -q file1 file2 > outfile + atf_check cmp outfile expectfile +} + +atf_test_case verbose_header +verbose_header_head() { + atf_set "descr" "Test head(1)'s verbose header feature" +} +verbose_header_body() { + #head(1) defaults to head -n 10 if no args are given. + jot -b test 10 > file1 + echo '==> file1 <==' > expectfile + cat file1 >> expectfile + head -v file1 > outfile + atf_check cmp outfile expectfile +} + +atf_test_case si_number +si_number_head() { + atf_set "descr" "Test head(1)'s SI number feature" +} +si_number_body() { + jot -b aaaaaaa 129 > file1 + jot -b aaaaaaa 128 > expectfile + head -c 1k file1 > outfile + atf_check cmp outfile expectfile + jot 1025 1 1025 > file1 + jot 1024 1 1024 > expectfile + head -n 1k file1 > outfile + atf_check cmp outfile expectfile +} + atf_init_test_cases() { atf_add_test_case empty_file atf_add_test_case default_no_options @@ -129,4 +171,7 @@ atf_init_test_cases() { atf_add_test_case missing_line_count atf_add_test_case invalid_line_count atf_add_test_case read_from_stdin + atf_add_test_case silent_header + atf_add_test_case verbose_header + atf_add_test_case si_number } |
