2009-12-29 32 views
6

Tôi mới làm kịch bản, nhưng tôi có rất nhiều kinh nghiệm lập trình bằng các ngôn ngữ như C# và Java.Tập lệnh Bash - Đọc tập tin nhị phân

Tôi có a file that contains binary data. Tôi muốn viết một kịch bản Bash đọc năm, tháng và ngày chứa trong tệp đó để tôi có thể sắp xếp các tệp MOD được liên kết thành các thư mục theo ngày chúng được ghi lại. Tôi đang gặp khó khăn khi tìm cách đọc dữ liệu nhị phân và phân tích cú pháp trong tập lệnh bash. Có cách nào để làm điều này không?

+0

ra khỏi tò mò, tại sao bash và không perl/python? – Amirshk

+2

Không có lý do thực sự. Tôi đã viết một tệp BASH để đổi tên các tệp và di chuyển chúng. Sau đó, tôi nghĩ sẽ tốt hơn nếu sắp xếp chúng khi các tập tin được ghi lại thay vì khi tôi sao chép chúng ra khỏi máy ảnh. – Joel

Trả lời

8

Bạn có thể sử dụng od (cộng đầu và chờ cho một chút chế biến sau) cho việc này. Để có được năm:

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

Trong tháng:

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

Và trong ngày:

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

hoạt động tuyệt vời. cảm ơn. Tôi thực sự tìm thấy một cách tốt hơn để có được ngày từ các tập tin hơn phân tích cú pháp dữ liệu nhị phân trước khi tôi đọc này. Nhưng mã này không làm những gì nó được cho là. Cảm ơn! – Joel

2

Tôi khuyên bạn nên sử dụng python cho việc này.

Tuy nhiên, nếu bạn nhấn mạnh vào bash, tôi sẽ thử sử dụng sed ở chế độ nhị phân (không bao giờ thử) hoặc sử dụng dd để trích xuất các byte cụ thể và sau đó chuyển đổi chúng.

0

bạn có thể tìm kiếm trên net cho mô-đun để diễn giải tệp MOI (hoặc Perl hoặc Python). Nếu không, tôi không thực sự nghĩ rằng bạn có thể nhận được ngày giống như thế từ tập tin nhị phân bởi vì nếu bạn nhìn vào bên trong, nó thực sự "rác" kể từ nhị phân của nó. Mặc dù bạn cũng có thể cung cấp cho các chuỗi lệnh một thử để xem nếu có là chuỗi rõ ràng phù hợp với ngày

1

Nếu đây không phải là quá Hardcore cho bạn tôi đề nghị biên soạn chương trình C-ngôn ngữ sau đây:

#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; 
} 

sau đó thực hiện điều này:

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

Bây giờ bạn có một công cụ hữu ích được gọi là 'ReadInt' với cú pháp sau:

readint [-o offset] [-t int32|uint32|int64|uint64 ] [-e little|big ] <filename> 
Các vấn đề liên quan