Frage

Ich bin neu im Scripting, aber ich habe viel Erfahrung in Sprachen wie C# und Java.

Ich habe Eine Datei, die binäre Daten enthält. 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 entsprechend dem Datum, an dem sie aufgezeichnet wurden, in Ordner sortieren kann. Ich habe Probleme, einen Weg zu finden, um binäre Daten zu lesen und sie in einem Bash -Skript zu analysieren. Gibt es eine Möglichkeit, dies zu tun?

War es hilfreich?

Lösung

Dafür können Sie OD (plus Head und Awk für ein wenig Nachbearbeitung) verwenden. Um das Jahr zu bekommen:

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 der Tag:

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

Andere Tipps

Ich würde empfehlen, Python dafür zu verwenden.

Wenn Sie jedoch auf Bash bestehen, würde ich versuchen, entweder zu verwenden sed im Binärmodus (nie ausprobiert) oder verwendet dd zum Extrahieren spezifischer Bytes und dann umwandeln.

Wenn dies für Sie nicht zu hardcore ist, empfehle ich, das folgende C-Sprachprogramm zu kompilieren:

#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 machen Sie das:

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

Jetzt haben Sie ein praktisches Tool namens "Readint" mit der folgenden Syntax:

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

Sie können das Netz nach Modulen durchsuchen, um MOI -Dateien (entweder Perl oder Python) zu interpretieren. Ansonsten glaube ich nicht wirklich, dass Sie das Datum einfach so aus der Binärdatei bekommen können, denn wenn Sie hineinschauen, ist es wirklich "Müll" seit seiner Binärdatei. Obwohl Sie dem Strings -Befehl auch versuchen können, zu sehen, ob es lesbare Zeichenfolgen gibt, die dem Datum übereinstimmen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top