スクリプトは初めてですが、C# や Java などの言語でのプログラミングの経験は豊富です。
バイナリ データを含むファイルがあります。そのファイルに含まれる年、月、日を読み取る Bash スクリプトを作成して、関連する MOD ファイルを記録された日付に従ってフォルダーに分類できるようにしたいと考えています。バイナリ データを読み取り、bash スクリプトで解析する方法を見つけるのに苦労しています。これを行う方法はありますか?
スクリプトは初めてですが、C# や Java などの言語でのプログラミングの経験は豊富です。
バイナリ データを含むファイルがあります。そのファイルに含まれる年、月、日を読み取る Bash スクリプトを作成して、関連する MOD ファイルを記録された日付に従ってフォルダーに分類できるようにしたいと考えています。バイナリ データを読み取り、bash スクリプトで解析する方法を見つけるのに苦労しています。これを行う方法はありますか?
これには od (少し後処理するための head と awk を追加) を使用できます。年を取得するには:
year=$(od -t x2 --skip-bytes=6 --read-bytes=2 file.moi | head -1 | awk '{print $2}')
月の場合:
month=$(od -t x1 --skip-bytes=8 --read-bytes=1 file.moi | head -1 | awk '{print $2}')
そしてその日:
day=$(od -t x1 --skip-bytes=9 --read-bytes=1 file.moi | head -1 | awk '{print $2}')
これにはpythonを使用することをお勧めします。
ただし、bashを主張する場合はsed
、バイナリモードで使用するか(試したことはありません)、dd
特定のバイトを抽出してから変換するために使用します。
これが難しすぎない場合は、次の C 言語プログラムをコンパイルすることをお勧めします。
#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;
}
次に、これを行います:
gcc -o readint readint.c
sudo mv readint /usr/local/bin
これで、次の構文を持つ「readint」という便利なツールができました。
readint [-o offset] [-t int32|uint32|int64|uint64 ] [-e little|big ] <filename>
MOI ファイル (Perl または Python) を解釈するためのモジュールをネットで検索できます。そうしないと、バイナリファイルからそのように日付を取得できるとは思えません。内部を見ると、バイナリであるため、実際には「ガベージ」だからです。日付に一致する判読可能な文字列があるかどうかを確認するために、strings コマンドを実行することもできますが、