2009-12-29 20 views
6

Ich bin neu im Skripting, habe aber viel Erfahrung in der Programmierung in Sprachen wie C# und Java.Bash Script - Binärdatei lesen

Ich habe a file that contains binary data. Ich möchte ein Bash-Skript schreiben, das das Jahr, den Monat und den Tag in dieser Datei liest, damit ich die zugehörigen MOD-Dateien nach dem Aufnahmedatum in Ordner sortieren kann. Ich habe Probleme, Binärdaten zu lesen und in einem Bash-Skript zu analysieren. Gibt es eine Möglichkeit, dies zu tun?

+0

Aus Neugier, warum Bash und nicht Perl/Python? – Amirshk

+2

Kein Grund wirklich. Ich habe bereits eine BASH-Datei geschrieben, um die Dateien umzubenennen und zu verschieben. Dann dachte ich, es wäre besser, sie nach der Aufnahme zu sortieren, als nach dem Kopieren von der Kamera. – Joel

Antwort

8

Sie können od (plus Kopf und awk für ein wenig Nachbearbeitung) dafür verwenden. Um das Jahr:

year=$(od -t x2 --skip-bytes=6 --read-bytes=2 file.moi | head -1 | awk '{print $2}') 

Für den Monat:

month=$(od -t x1 --skip-bytes=8 --read-bytes=1 file.moi | head -1 | awk '{print $2}') 

Und den Tag:

day=$(od -t x1 --skip-bytes=9 --read-bytes=1 file.moi | head -1 | awk '{print $2}') 
+0

funktioniert gut. Vielen Dank. Ich habe einen besseren Weg gefunden, das Datum von den Dateien zu bekommen, als die Binärdaten zu analysieren, bevor ich das lese. Aber dieser Code tut, was er soll. Vielen Dank! – Joel

2

Ich würde die Verwendung von Python dafür empfehlen.

Wenn Sie jedoch auf Bash bestehen, würde ich versuchen, entweder sed im Binärmodus (nie probiert) oder mit dd zum Extrahieren bestimmter Bytes und dann konvertieren sie.

0

Sie im Netz nach Modulen suchen zu MOI Dateien zu interpretieren (entweder Perl oder Python). Ansonsten denke ich nicht wirklich, dass du das Datum einfach so aus der Binärdatei bekommen kannst, denn wenn du hineinschaust, ist es wirklich "Müll" seit seiner Binärdatei. Obwohl Sie auch die Saiten Befehl einen Versuch geben kann, wenn es zu sehen lesbaren Zeichenketten sind, die

1

Wenn dies nicht zu dem Datum übereinstimmen für Sie hardcore ist schlage ich die folgende C-Sprachenprogramm kompiliert:

#include <stdio.h> 
#include <inttypes.h> 

typedef union { 
    char array[sizeof(int32_t)]; 
    int32_t val; 
} int32_u; 

typedef union { 
    char array[sizeof(uint32_t)]; 
    uint32_t val; 
} uint32_u; 

typedef union { 
    char array[sizeof(uint64_t)]; 
    uint64_t val; 
} uint64_u; 

typedef union { 
    char array[sizeof(int64_t)]; 
    int64_t val; 
} int64_u; 

int swap(char* mem, int size) { 
    if (size & 1 != 0) 
    return -1; 
    int i; 
    for (i = 0; i < size/2; i++) { 
    char tmp = mem[i]; 
    mem[i] = mem[size - i - 1]; 
    mem[size - i - 1] = tmp; 
    } 
    return 0; 
} 

int sys_big_endian() { 
    int x = 1; 
    return !(*(char*)&x); 
} 

int main(int argc, char** argv) { 
    char* file_name = NULL; 
    int offset = 0; 
    char* type = "int32"; 
    int big_endian = 0; 

    int i; 
    for(i = 1; i < argc; i++) { 
    if(!strncmp("-o", argv[i], 2)) { 
     ++i; 
     sscanf(argv[i], "%d", &offset); 
    } else if(!strncmp("-t", argv[i], 2)) { 
     ++i; 
     type = argv[i]; 
    } else if(!strncmp("-e", argv[i], 2)) { 
     ++i; 
     big_endian = !strncmp("big", argv[i], 3); 
    } else { 
     file_name = argv[i]; 
     break; 
    } 
    } 

    if (i < argc - 1) { 
    fprintf(stderr, "Ignoring extra arguments: "); 
    ++i; 
    for (; i < argc; i++) { 
     fprintf(stderr, "%s ", argv[i]); 
    } 
    fprintf(stderr, "\n"); 
    } 

    if (file_name == NULL) { 
    fprintf(stderr, "Syntax: readint [-o offset] [-t type] [-e endian] <filename>\n" 
     "Where:\n" 
     " type  'uint32', 'uint64', 'int32' (default), 'int64'.\n" 
     " endian 'big' or 'little' (default).\n" 
     " offset offset in a file from where the read will happen, default is 0.\n" 
    ); 
    return -1; 
    } 

    FILE* fp = fopen(file_name, "rb"); 

    if (fp == NULL) { 
    fprintf(stderr, "Could not open the file: %s\n", file_name); 
    return -1; 
    } 

    fseek(fp, offset, SEEK_SET); 

    if (!strncmp("uint32", type, 6)) { 
    uint32_u u; 
    fread(u.array, sizeof(u.array), 1, fp); 
    if (big_endian^sys_big_endian()) 
     swap(u.array, sizeof(u.array)); 
    printf("%u\n", u.val); 
    } else if (!strncmp("int32", type, 5)) { 
    int32_u u; 
    fread(u.array, sizeof(u.array), 1, fp); 
    if (big_endian^sys_big_endian()) 
     swap(u.array, sizeof(u.array)); 
    printf("%d\n", u.val); 
    } else if (!strncmp("uint64", type, 6)) { 
    uint64_u u; 
    fread(u.array, sizeof(u.array), 1, fp); 
    if (big_endian^sys_big_endian()) 
     swap(u.array, sizeof(u.array)); 
    printf("%"PRIu64"\n", u.val); 
    } else if (!strncmp("int64", type, 5)) { 
    int64_u u; 
    fread(u.array, sizeof(u.array), 1, fp); 
    if (big_endian^sys_big_endian()) 
     swap(u.array, sizeof(u.array)); 
    printf("%"PRId64"\n", u.val); 
    } else { 
    printf("Unknown type: %s\n", type); 
    } 

    fclose(fp); 
    return 0; 
} 

dann tun Sie dies:

gcc -o readint readint.c 
sudo mv readint /usr/local/bin 

Jetzt haben Sie ein handliches Werkzeug 'readInt' mit folgenden Syntax aufgerufen:

readint [-o offset] [-t int32|uint32|int64|uint64 ] [-e little|big ] <filename>