head, tail, fold コマンド

コマンドラインでの head,tail,fold コマンドを実行する例題です.

head, tail コマンドでバイナリファイルを開くと改行文字が含まれていないため,一行に大量の文字列が表示されることになり,上手く表示されません.今回の例題では,fold コマンドのように,指定された文字数で文字列を折り返し,head, tail の結果を整形・表示しています.

head(list_80-1.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

//------------------------------------------------------------
void usage(char* cmd);
void myhead(char* infile,int n_output,int n_fold);
//------------------------------------------------------------

int main(int argc,char* argv[])
{
    int i;
    static int n_output=10,n_fold=0;
    char *in_file=NULL;
    // read argument
    for(i=1;i<argc;i++){
        if(argv[i][0] == '-'){
            switch(argv[i][1]){
            case 'n':
                if(argv[++i] == NULL){
                    fprintf(stderr,"Output number err.\n");
                    usage(argv[0]);
                    return 0;
                }
                n_output = atoi(argv[i]);
                break;
            case 'f':
                if(argv[++i] == NULL){
                    fprintf(stderr,"Fold number not err.\n");
                    usage(argv[0]);
                    return 0;
                }
                n_fold = atoi(argv[i]);
                break;
            default:
                fprintf(stderr,"Unknown option '%c'\n",argv[i][1]);
                usage(argv[0]);
                return 0;
            }
        } else {
            in_file = argv[i];
        }
    }
    if(in_file == NULL){
        usage(argv[0]); return 0;
    }

    myhead(in_file,n_output,n_fold);
    
    return 0;
}

void usage(char* cmd)
{
    printf("usage: %s in_file [option]\n",cmd);
    printf("[option]:\n");
    printf("  -n number: set output line number\n");
    printf("  -f number: set fold number\n");
}

//------------------------------------------------------------
// ファイル先頭部の表示
//------------------------------------------------------------
void myhead(char* infile,int n_output,int n_fold)
{
    char c,old_c;
    long n_byte,n_line;
    int infd = open(infile,O_RDONLY);
    if(infd < 0){
        perror(infile);
        return;
    }
    // output head
    n_byte = n_line = 0;
    while(n_line < n_output){
        if(read(infd,&c,1) <= 0) break;
        old_c = c;
        if(c != '\7') write(1,&c,1);
        if(c == '\n' || (n_fold && ++n_byte >= n_fold)){
            n_byte = 0; n_line++;
            if(c!='\n'){
                old_c = '\n';
                write(1,"\n",1);
            }
        }
    }
    if(old_c != '\n') write(1,"\n",1);
    close(infd);
}















実行結果
Gami[1813]% ./myhead myhead.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

//------------------------------------------------------------
void usage(char* cmd);
void myhead(char* infile,int n_output,int n_fold);
//------------------------------------------------------------
Gami[1814]% ./myhead myhead.exe -n 10 -f 30
MZ         ク       @

氈  室 雫      赦!失L赦!This program
 cannot be run in DOS mode.
$       PE  L 6邪爾B   
8             
  @                     `
     (H                
                P  車

Gami[1815]%

tail(list_80-2.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

//------------------------------------------------------------
void usage(char* cmd);
void mytail(char* infile,int n_output,int n_fold);
//------------------------------------------------------------

int main(int argc,char* argv[])
{
    int i,n_output=10,n_fold=0;
    char *in_file=NULL;
    // read argument
    for(i=1;i<argc;i++){
        if(argv[i][0] == '-'){
            switch(argv[i][1]){
            case 'n':
                if(argv[++i] == NULL){
                    fprintf(stderr,"Output number not err.\n");
                    usage(argv[0]);
                    return 0;
                }
                n_output = atoi(argv[i]);
                break;
            case 'f':
                if(argv[++i] == NULL){
                    fprintf(stderr,"Fold number not err.\n");
                    usage(argv[0]);
                    return 0;
                }
                n_fold = atoi(argv[i]);
                break;
            default:
                fprintf(stderr,"Unknown option '%c'\n",argv[i][1]);
                usage(argv[0]);
                return 0;
            }
        } else {
            in_file = argv[i];
        }
    }
    if(in_file == NULL){
        usage(argv[0]); return 0;
    }

    mytail(in_file,n_output,n_fold);
    
    return 0;
}

void usage(char* cmd)
{
    printf("usage: %s in_file [option]\n",cmd);
    printf("[option]:\n");
    printf("  -n number: set output line number\n");
    printf("  -f number: set fold number\n");
}

//------------------------------------------------------------
// ・ユ・。・、・良充/span>
//------------------------------------------------------------
void mytail(char* infile,int n_output,int n_fold)
{
    off_t oft;
    char c,old_c;
    int n_byte,n_line;
    int infd = open(infile,O_RDONLY);
    if(infd < 0){
        perror(infile);
        return;
    }
    // seek tail
    n_byte = n_line = 0;
    oft = lseek(infd,0,SEEK_END);
    oft = lseek(infd,oft-1,SEEK_SET);
    read(infd,&c,1); n_byte++;
    if(c != '\n') { n_line++; n_byte = 0; }
    while(n_line <= n_output){
        if((oft = lseek(infd,oft-1,SEEK_SET)) < 0) {
            lseek(infd,0,SEEK_SET); break;
        }
        read(infd,&c,1);
        if(c=='\n' || (n_fold && ++n_byte >= n_fold)) {
            n_byte = 0; n_line ++;
            if(c=='\n') oft = lseek(infd,oft-1,SEEK_SET);
        }
    }
    oft = lseek(infd,oft+2,SEEK_SET);
    // output tail
    n_byte = 0;
    while(read(infd,&c,1)){
        n_byte ++; old_c = c;
        if(c!='\7') write(1,&c,1);
        if(c=='\n' || (n_fold && n_byte >= n_fold)){
            n_byte = 0;
            if(c!='\n'){
                old_c = '\n'; write(1,"\n",1);
            }
        }
    }
    if(old_c!='\n') write(1,"\n",1);
    close(infd);
}

実行結果
Gami[1815]% ./mytail mytail.c
                if(c=='\n' || (n_fold && n_byte >= n_fold)){
                        n_byte = 0;
                        if(c!='\n'){
                                old_c = '\n'; write(1,"\n",1);
                        }
                }
        }
        if(old_c!='\n') write(1,"\n",1);
        close(infd);
}
Gami[1816]% ./mytail mytail.exe -n 10 -f 30
ocess __imp__free __major_imag
e_version__ __loader_flags__ _
_imp__printf __imp__AddAtomA@4
 _pthread_atfork __head_libker
nel32_a __minor_subsystem_vers
ion__ __minor_image_version__
_FindAtomA@4 _GetAtomNameA@12
__RUNTIME_PSEUDO_RELOC_LIST_EN
D__ __libkernel32_a_iname __im
p___lseek64 ___crt_xt_end__
Gami[1817]%
inserted by FC2 system