makefile สามารถตรวจพบว่าคำสั่งมีอยู่ในเครื่องโลคอลได้อย่างไร


11

ฉันเริ่มใช้โหมดองค์กรเพื่อวางแผนงานของฉันในระบบสไตล์GTD การวางทุกไฟล์องค์กรลงในไดเรกทอรีของโฟลเดอร์Dropboxฉันเรียกใช้ emacs เพื่อแก้ไข / จัดการไฟล์เหล่านี้จากเครื่องที่แตกต่างกันสามเครื่อง: Cygwin, Mac OS X และ Debian เมื่อฉันใช้MobileOrgเพื่อเข้าถึงไฟล์ org เหล่านี้จาก iPad ของฉันchecksums.datไฟล์จะต้องได้รับการอัปเดตเมื่อมีการเปลี่ยนแปลง md5sum *.org > checksums.datซึ่งสามารถทำได้โดยการทำงาน

ปัญหาคือมีคำสั่งต่างกันสามคำสั่งสำหรับmd5sum: md5sum.exeใน Cygwin, md5ใน Mac OS X และmd5sumใน Debian สถานการณ์ที่เหมาะสมที่สุดคือ makefile ซึ่งเก็บไว้ใน Dropbox foder ตรวจพบคำสั่งที่มีอยู่ในเครื่องปัจจุบันและเรียกใช้คำสั่งนั้นเพื่อทำการดำเนินการตรวจสอบ md5



1
@ เควินนั่นฟังดูเหมือน overkill ฉันไม่ต้องการติดตั้งโปรแกรมในสามระบบที่แตกต่างกัน ในแต่ละระบบโฟลเดอร์ Dropbox จะสามารถเข้าถึงได้ในรูปแบบไดเรกทอรีในระบบ เมื่อฉันเรียกใช้make checksumเพื่อสร้างข้อมูล checksum ภายใต้โฟลเดอร์ Dropbox ฉันต้องการให้ makefile ใช้คำสั่งที่เหมาะสมหลังจากตรวจสอบคำสั่ง checksum ที่มีอยู่ในเครื่องปัจจุบัน
Federico Magallanez

หากคุณกำลังจะทำสคริปต์จำนวนมากและโปรเจ็กต์มีขนาดเล็ก
Faheem Mitha

คำตอบ:


7

คำสั่งที่เป็นไปได้ในการสร้างการตรวจสอบ

น่าเสียดายที่ไม่มียูทิลิตี้มาตรฐานในการสร้างการตรวจสอบการเข้ารหัสลับ มีสาธารณูปโภคที่ได้มาตรฐานในการสร้างซีอาร์ซีคือcksum; สิ่งนี้อาจเพียงพอสำหรับวัตถุประสงค์ของคุณในการตรวจจับการเปลี่ยนแปลงในสภาพแวดล้อมที่ไม่เป็นมิตร

ฉันจะแนะนำให้ใช้ SHA1 มากกว่า MD5 มีหลายระบบที่มียูทิลิตี MD5 แต่ไม่มี SHA1 และถ้าคุณจะใช้การตรวจสอบการเข้ารหัสลับคุณอาจใช้อัลกอริทึมที่ไม่มีเมธอดที่รู้จักเพื่อค้นหาการชนกัน (สมมติว่าคุณตรวจสอบขนาดด้วย)

เครื่องมืออย่างหนึ่งที่ไม่ได้มาตรฐาน แต่ที่พบบ่อยและสามารถคำนวณย่อยสลายเป็นOpenSSL มีให้สำหรับ Cygwin, Debian และ OSX แต่น่าเสียดายที่ไม่ได้เป็นส่วนหนึ่งของการติดตั้งเริ่มต้นบน OSX

openssl dgst -sha1

ใน OSX 10.6 มีshasumยูทิลิตี้ซึ่งมีอยู่ใน Debian (เป็นส่วนหนึ่งของperlแพ็คเกจ) และฉันก็เชื่อใน Cygwin ด้วย นี่คือสคริปต์ Perl ระบบ unix ส่วนใหญ่มีการติดตั้ง Perl ดังนั้นคุณสามารถรวมสคริปต์นั้นไว้ข้าง makefile ของคุณหากคุณกังวลว่าสคริปต์นี้จะไม่สามารถใช้ได้ทุกที่

การเลือกคำสั่งที่เหมาะสมสำหรับระบบของคุณ

เอาล่ะสมมติว่าคุณไม่สามารถหาคำสั่งที่ใช้งานได้ทุกที่

ในเปลือก

ใช้typeบิวด์อินเพื่อดูว่ามีคำสั่งอยู่หรือไม่

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 ทำ

คุณสามารถใช้shellฟังก์ชั่นเพื่อเรียกใช้ shell snippet เมื่อโหลดไฟล์และเก็บเอาต์พุตในตัวแปร

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

ทำให้พกพา (POSIX)

คุณสามารถเรียกใช้คำสั่งเชลล์ในกฎดังนั้นแต่ละกฎที่คำนวณ checksum จะต้องมีรหัสการค้นหา คุณสามารถวางตัวอย่างในตัวแปร โปรดจำไว้ว่าบรรทัดแยกต่างหากในกฎจะถูกประเมินโดยอิสระ ยังจำได้ว่าสัญญาณว่าจะได้รับการส่งผ่านไปยังเปลือกจำเป็นที่จะหนีไป$$$

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

ผมต้องใช้-Pตัวเลือกของtypeคำสั่งในการสั่งซื้อที่จะได้รับ "GNU ทำให้" sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null)วิธีการที่อธิบายข้างต้นในการทำงานอย่างถูกต้องดังนั้นผมจึงจบลงด้วย
Sean

@Sean ขอบคุณสำหรับรายงานข้อผิดพลาด type -Pใช้งานได้เฉพาะถ้าเชลล์ของคุณทุบตีเท่านั้นไม่ใช่ถ้าเป็นเช่น ksh หรือ dash (ซึ่งเป็นกรณีของ Ubuntu ในกลุ่มอื่น ๆ ) คุณสามารถใช้command -vเพื่อการพกพา
Gilles 'หยุดความชั่วร้าย'

ดูเหมือนว่าคุณได้เปลี่ยนจากการใช้กับการใช้type commandควรปรับปรุงวิธีอื่นด้วยหรือไม่
Sean

@Sean วิธีการอื่นดี: typeเป็นวิธีพกพาที่ถูกต้องเพื่อทดสอบการมีอยู่ของคำสั่งปัญหาที่เกิดขึ้นคือมันสร้างเอาต์พุตเหมือนsha1sum is /usr/bin/sha1sumไม่ใช่แค่ชื่อโปรแกรม นี่เป็นที่เดียวที่ฉันใช้เอาต์พุตtypeแทนที่จะเป็นแค่ค่าส่งคืน
Gilles 'หยุดความชั่วร้าย'

5

มันเป็นเรื่องของการแฮ็ค แต่คุณสามารถทดสอบว่ามีอยู่หรือไม่และจะดำเนินการหากพวกเขาทำ:

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

ฉันค่อนข้างแน่ใจว่า cygwin จดจำคำสั่ง (รวมถึงmd5sum) โดยไม่มี.exeแต่ให้รวมไว้หากคุณต้อง


4
whichค่าการออกไม่สามารถเคลื่อนย้ายได้ ใช้typeแทน (และคุณอาจต้องการใช้if; then; elifเพื่อหลีกเลี่ยงปัญหาในการมีหลายโปรแกรม) whichและtypeมองหาไฟล์ที่เรียกทำงานได้เท่านั้นดังนั้นการทดสอบด้วย -x นั้นไม่มีประโยชน์
Chris Down

เพิ่มเติมเกี่ยวกับการใช้ "type": cmd = $ (สำหรับ cmd ใน foo md5 md5sum bar; ให้พิมพ์ $ cmd> / dev / null 2> & 1 && & echo $ cmd && ทำลาย;) $ cmd file1 file2 file3> md5.txt
michael


1

อาจเป็นเครื่องมืออัตโนมัติ GNU (ตามที่กล่าวไว้ในความคิดเห็น) หรือCMakeเป็นตัวเลือก

เครื่องมืออัตโนมัติของ GNU เป็นวิธีการแบบดั้งเดิมมากขึ้น แต่ (และบางทีอาจจะพูดเพื่อตัวเองเท่านั้น) ฉันไม่คิดว่าผู้คนจะตื่นเต้นเกินไปที่จะคาดหวังในการเริ่มต้นโครงการโดยใช้พวกเขา มันเป็นช่วงการเรียนรู้ไม่ว่าในกรณีใด CMake เป็นเด็กรุ่นใหม่ในบล็อกและอาจจะน้อยกว่าปกติ (และยังมีช่วงการเรียนรู้) มันมีไวยากรณ์ของตัวเองและสร้าง makefiles สำหรับแพลตฟอร์มของคุณ CMake มีข้อได้เปรียบที่แตกต่างกันของการไม่เป็นเช่นนั้น * x-centric มันทำงานได้อย่างน่าเชื่อถือใน unix, windows และ mac เช่นกัน (เช่นสามารถสร้างโครงการ msvc ตัวอย่างเช่นแทนที่จะเป็น makefiles)

แก้ไข: และแน่นอนตั้งแต่แนะนำ 'makefiles' คำตอบนี้จะสอดคล้องกับข้อสันนิษฐานนั้น แต่อาจเป็นเพียงสคริปต์ไพ ธ อนหรือ (gasp) โปรแกรม Java อย่างง่ายจะเหมาะสมกว่าสำหรับงานนี้ ภาษาสคริปต์ / การเขียนโปรแกรมจะทำเช่นนี้ข้ามแพลตฟอร์ม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.