Làm thế nào một makefile có thể phát hiện xem một lệnh có sẵn trong máy cục bộ không?


11

Tôi bắt đầu sử dụng chế độ org để lập kế hoạch cho các nhiệm vụ của mình trong hệ thống kiểu GTD . Đặt mọi tệp org vào một thư mục của thư mục Dropbox , tôi chạy emacs để chỉnh sửa / quản lý các tệp này từ ba máy cục bộ khác nhau: Cygwin, Mac OS X và Debian. Vì tôi cũng sử dụng MobileOrg để truy cập các tệp org này từ iPad của mình, một checksums.dattệp phải được cập nhật khi có bất kỳ thay đổi nào được thực hiện. Điều này có thể được thực hiện bằng cách chạy md5sum *.org > checksums.dat.

Vấn đề là có ba lệnh khác nhau cho md5sumlệnh: md5sum.exetrong Cygwin, md5trong Mac OS X và md5sumtrong Debian. Tình huống lý tưởng nhất là tệp tạo tệp, được lưu trữ trong bộ mã hóa Dropbox, phát hiện lệnh nào có sẵn trong máy hiện tại và chạy lệnh đó để thực hiện thao tác kiểm tra md5.



1
@Kevin Nghe có vẻ quá mức. Tôi không muốn cài đặt một chương trình trong ba hệ thống riêng biệt. Trong mỗi hệ thống, thư mục Dropbox có thể truy cập dưới dạng thư mục cục bộ. Khi tôi chạy make checksumđể tạo dữ liệu tổng kiểm tra trong thư mục Dropbox, tôi muốn tệp Makefile sử dụng một lệnh thích hợp sau khi phát hiện lệnh tổng kiểm tra nào có sẵn trong máy hiện tại.
Federico Magallanez

Nếu bạn định thực hiện một số lượng đáng kể kịch bản và dự án còn nhỏ, tôi sẽ đề xuất các chương trình.
Faheem Mitha

Câu trả lời:


7

Các lệnh có thể để tạo tổng kiểm tra

Thật không may, không có tiện ích tiêu chuẩn để tạo tổng kiểm tra mật mã. Có một tiện ích tiêu chuẩn để tạo CRC : cksum; điều này có thể đủ cho mục đích phát hiện những thay đổi trong môi trường không thù địch của bạn.

Tôi khuyên bạn nên sử dụng SHA1 thay vì MD5. Không có nhiều hệ thống có tiện ích MD5 nhưng không có SHA1 và nếu bạn sẽ sử dụng tổng kiểm tra mật mã, bạn cũng có thể sử dụng thuật toán không có phương pháp đã biết để tìm xung đột (giả sử bạn cũng kiểm tra kích thước).

Một công cụ không chuẩn nhưng phổ biến và có thể tính toán các tiêu hóa là OpenSSL . Nó có sẵn cho Cygwin, Debian và OSX, nhưng tiếc là không phải là một phần của cài đặt mặc định trên OSX.

openssl dgst -sha1

Trên OSX 10.6, có một shasumtiện ích, cũng có trên Debian (nó là một phần của perlgói) và tôi cũng tin vào Cygwin. Đây là một kịch bản Perl. Hầu hết các hệ thống unix đã cài đặt Perl, vì vậy bạn có thể gói tập lệnh đó cùng với tệp tạo tệp của mình nếu bạn lo lắng về tập lệnh này không có sẵn ở mọi nơi.

Chọn lệnh đúng cho hệ thống của bạn

Ok, giả sử bạn thực sự không thể tìm thấy một lệnh hoạt động ở mọi nơi.

Trong vỏ

Sử dụng tích typehợp để xem nếu một lệnh có sẵn.

sum=
for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do
  if type "${x%% *}" >/dev/null 2>/dev/null; then sum=$x; break; fi
done
if [ -z "$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi
$sum *.org

GNU làm

Bạn có thể sử dụng shellchức năng để chạy đoạn mã shell khi tệp makefile được tải và lưu trữ đầu ra trong một biến.

sum := $(shell { command -v sha1sum || command -v sha1 || command -v shasum; } 2>/dev/null)
%.sum: %
        $(sum) $< >$@

Di động (POSIX)

Bạn chỉ có thể chạy các lệnh shell trong quy tắc, vì vậy mỗi quy tắc tính toán tổng kiểm tra phải chứa mã tra cứu. Bạn có thể đặt đoạn mã trong một biến. Hãy nhớ rằng các dòng riêng biệt trong các quy tắc được đánh giá độc lập. Cũng cần nhớ rằng $các dấu hiệu được truyền vào vỏ cần phải được thoát ra $$.

determine_sum = \
        sum=; \
        for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do \
          if type "$${x%% *}" >/dev/null 2>/dev/null; then sum=$$x; break; fi; \
        done; \
        if [ -z "$$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi

checksums.dat: FORCE
    $(determine_sum); \
    $$sum *.org

Tôi đã phải sử dụng -Ptùy chọn của typelệnh để có được phương thức "GNU make" được mô tả ở trên để hoạt động chính xác, vì vậy tôi đã kết thúc với sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null).
Sean

@Sean Cảm ơn báo cáo lỗi. type -Pchỉ hoạt động nếu shell của bạn bị bash, không phải nếu nó là ksh hoặc dash (đó là trường hợp trên Ubuntu trong số những cái khác). Bạn có thể sử dụng command -vcho tính di động.
Gilles 'SO- đừng trở nên xấu xa'

Có vẻ như bạn đã chuyển từ sử dụng typesang sử dụng command. Các phương pháp khác có nên được cập nhật không?
Sean

@Sean Các phương thức khác đều ổn: typelà một cách chính xác, di động để kiểm tra sự hiện diện của lệnh, vấn đề với nó là nó tạo ra đầu ra như thế sha1sum is /usr/bin/sha1sumchứ không chỉ là tên chương trình. Đây là nơi duy nhất mà tôi sử dụng đầu ra của typechứ không chỉ giá trị trả về của nó.
Gilles 'SO- ngừng trở nên xấu xa'

5

Đó là một cái gì đó của hack, nhưng bạn có thể kiểm tra xem từng tồn tại và thực thi chúng nếu chúng thực hiện:

[ -x "`which md5 2>/dev/null`" ] && md5 newfile >>sums
[ -x "`which md5sum 2>/dev/null`" ] && md5sum newfile >>sums

Tôi khá chắc chắn Cygwin nhận ra các lệnh (bao gồm md5sum) mà không có .exe, nhưng bao gồm nó nếu bạn phải.


4
whichgiá trị thoát không phải là di động. Sử dụng typethay thế (và bạn có thể muốn sử dụng if; then; elifđể tránh gặp sự cố trong đó có nhiều tệp thực thi). whichtypechỉ tìm kiếm các tệp thực thi, vì vậy thử nghiệm của bạn với -x là vô nghĩa.
Chris Down

thêm về cách sử dụng "type": cmd = $ (đối với cmd trong thanh foo md5 md5sum; hãy gõ $ cmd> / dev / null 2> & 1 && echo $ cmd && break; xong); $ cmd file1 file2 file3> md5.txt
michael


1

Hoặc GNU autotools (như đã đề cập trong một chú thích), hoặc cũng CMake là một lựa chọn.

GNU autotools là cách tiếp cận truyền thống hơn, nhưng (và có lẽ chỉ nói cho bản thân tôi) Tôi không nghĩ mọi người thực sự quá phấn khích trước viễn cảnh ban đầu thiết lập dự án bằng cách sử dụng chúng. Vâng, đó là một đường cong học tập, trong mọi trường hợp. CMake là đứa trẻ mới hơn trong khối, và có lẽ ít phổ biến hơn (và vẫn có một lộ trình học tập). Nó có cú pháp riêng của nó và nó tạo ra các tệp tạo tệp cho nền tảng của bạn. CMake có lợi thế khác biệt là không quá un * x-centric; nó hoạt động đáng tin cậy trên unix, windows và mac (ví dụ, nó có thể tạo các dự án msvc, ví dụ, thay vì makefiles.)

Chỉnh sửa: và tất nhiên vì 'makefiles' đã được đề xuất, câu trả lời này đi cùng với giả định đó. Nhưng có lẽ chỉ cần một kịch bản python hoặc (gasp) một chương trình Java đơn giản sẽ phù hợp hơn cho nhiệm vụ này; ngôn ngữ lập trình / lập trình sẽ làm điều này giống nhau trên các nền tảng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.