มีคำสั่งเช่น "ดู" หรือ "inotifywait" บน Mac หรือไม่?


287

ฉันต้องการดูโฟลเดอร์บน Mac ของฉัน (Snow Leopard) จากนั้นเรียกใช้สคริปต์ (ให้ชื่อไฟล์ของสิ่งที่เพิ่งย้ายเข้าไปในโฟลเดอร์ (เป็นพารามิเตอร์ ... x.sh "filename")

ฉันมีสคริปต์ทั้งหมดเขียนขึ้นใน bash (x.sh) ที่จะย้ายไฟล์บางอย่างและสิ่งอื่น ๆ ในอินพุต $ 1 ฉันแค่ต้องการ OSX เพื่อให้ฉันชื่อไฟล์เมื่อไฟล์ / โฟลเดอร์ใหม่ถูกย้าย / สร้างเป็น dir

คำสั่งใด ๆ


1
คุณควรถามว่า DropBox ทำเช่นไรเพราะพวกเขาลองใช้ตัวเลือกที่มีทั้งหมด
Jeff Burdges

2
@JeffBurdges ฉันไม่แน่ใจว่านั่นเป็นเรื่องง่าย อย่างไรก็ตามฉันจะบอกว่าหลังจากอ่านข้ามการอ้างอิง FSEventsของ Apple มันจะโง่มากหาก Dropbox ไม่ได้ใช้ประโยชน์จากสิ่งนี้ fswatchutil นำเสนอเป็นคำตอบด้านล่างในความเป็นจริงการใช้วิธีการนี้
Steven Lu

คำตอบ:


447

fswatch

fswatchเป็นโปรแกรมขนาดเล็กที่ใช้ Mac OS X FSEvents API เพื่อตรวจสอบไดเรกทอรี เมื่อได้รับเหตุการณ์เกี่ยวกับการเปลี่ยนแปลงใด ๆ ในไดเร็กทอรีนั้นคำสั่งเชลล์ที่ระบุจะถูกเรียกใช้งานโดย/bin/bash

หากคุณใช้ GNU / Linux inotifywatch (เป็นส่วนหนึ่งของ inotify-toolsแพ็คเกจสำหรับการแจกจ่ายส่วนใหญ่) จะมีฟังก์ชั่นที่คล้ายกัน

อัปเดต: fswatchตอนนี้สามารถใช้ได้กับหลาย ๆ แพลตฟอร์มรวมถึง BSD, Debian และ Windows

ไวยากรณ์ / ตัวอย่างง่ายๆ

วิธีใหม่ที่สามารถรับชมได้หลายเส้นทาง - สำหรับเวอร์ชั่น 1.x และสูงกว่า :

fswatch -o ~/path/to/watch | xargs -n1 -I{} ~/script/to/run/when/files/change.sh

หมายเหตุ: การส่งออกโดยจำนวน-oจะได้รับการเพิ่มในตอนท้ายของคำสั่งหากไม่ได้สำหรับxargs -I{}หากคุณเลือกที่จะใช้หมายเลขนั้นให้วางที่{}ใดก็ได้ในคำสั่งของคุณ

วิธีที่เก่ากว่าสำหรับเวอร์ชั่น 0.x :

fswatch ~/path/to/watch ~/script/to/run/when/files/change.sh

ติดตั้งด้วย Homebrew

ตั้งแต่วันที่ 9/12/56 มันถูกเพิ่มเข้ามาในhomebrew - yay! ดังนั้นอัปเดตรายการสูตรของคุณ ( brew update) จากนั้นทั้งหมดที่คุณต้องทำคือ:

brew install fswatch

การติดตั้งโดยไม่ต้อง Homebrew

พิมพ์คำสั่งเหล่านี้ใน Terminal.app

cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch

หากคุณไม่มีcคอมไพเลอร์ในระบบของคุณคุณอาจต้องติดตั้ง Xcode หรือเครื่องมือบรรทัดคำสั่ง Xcode - ทั้งฟรี แต่ถ้าเป็นกรณีที่คุณอาจจะเป็นเพียงแค่ตรวจสอบ homebrew

ตัวเลือกเพิ่มเติมสำหรับfswatchเวอร์ชั่น 1.x

Usage:
fswatch [OPTION] ... path ...

Options:
 -0, --print0          Use the ASCII NUL character (0) as line separator.
 -1, --one-event       Exit fsw after the first set of events is received.
 -e, --exclude=REGEX   Exclude paths matching REGEX.
 -E, --extended        Use exended regular expressions.
 -f, --format-time     Print the event time using the specified format.
 -h, --help            Show this message.
 -i, --insensitive     Use case insensitive regular expressions.
 -k, --kqueue          Use the kqueue monitor.
 -l, --latency=DOUBLE  Set the latency.
 -L, --follow-links    Follow symbolic links.
 -n, --numeric         Print a numeric event mask.
 -o, --one-per-batch   Print a single message with the number of change events.
                       in the current batch.
 -p, --poll            Use the poll monitor.
 -r, --recursive       Recurse subdirectories.
 -t, --timestamp       Print the event timestamp.
 -u, --utc-time        Print the event time as UTC time.
 -v, --verbose         Print verbose output.
 -x, --event-flags     Print the event flags.

See the man page for more information.

คำแนะนำหรือการติดตั้งโดยไม่มี homebrew ดูเหมือนจะไม่ทำงานอีกต่อไป makeโยนข้อผิดพลาดเกี่ยวกับการไม่ค้นหา makefile โชคดีที่ตอนนี้ fswatch อยู่ใน MacPorts แล้วsudo port install fswatchใช้ได้ผลสำหรับพวกเราที่ใช้ MacPorts แทน Homebrew
coredumperror

หากคุณกำลังใช้คำสั่งที่มีอาร์กิวเมนต์แบบคงที่ (ตัวอย่างเช่นฉันใช้การทดสอบหน่วยของฉันกับการเปลี่ยนแปลง src และการทดสอบ) สิ่งนี้อาจไม่ทำงานสำหรับคุณ คำถามนี้ ( stackoverflow.com/questions/25689589/… ) เป็นคำถามชิ้นที่สองที่ฉันต้องการ
jskulski

5
ฉันได้ยินคุณออกไปที่นั่น:fswatch ./ | xargs -I{} cp {} ~/Dropbox/backup/latest/
fionbio

fswatch ดีกว่าเครื่องมือเช่น entr หรือ when_changed ซึ่งมีข้อบกพร่องบางอย่างเมื่อจัดการกับไดเรกทอรี. git fswatch เป็นมืออาชีพมากขึ้น เพียงแค่คุณfswatch .จะตรวจสอบไดเรกทอรีปัจจุบัน
ไม่ระบุชื่อ

ฉันจะแนะนำfswatch -0 -v -o /path/to/watched/files | xargs -0 -n 1 -I {} [your command]ด้วย-0สำหรับ NULLs อันนี้ใช้ได้กับฉันสำหรับการรวบรวมน้อย
หนานิก

95

คุณสามารถใช้launchdเพื่อจุดประสงค์นั้น Launchd สามารถกำหนดค่าให้เรียกใช้งานโปรแกรมโดยอัตโนมัติเมื่อมีการแก้ไขพา ธ ไฟล์

ตัวอย่างเช่นตัวกำหนดค่าการเรียกใช้งานต่อไปนี้จะเริ่มต้นโปรแกรม/usr/bin/loggerเมื่อโฟลเดอร์เดสก์ท็อปของบัญชีผู้ใช้ของฉันถูกแก้ไข:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>logger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/logger</string>
        <string>path modified</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Users/sakra/Desktop/</string>
    </array>
</dict>
</plist>

หากต้องการเปิดใช้งานโปรแกรมกำหนดค่าให้บันทึกลงในโฟลเดอร์ LaunchAgents ในโฟลเดอร์ Library ของคุณเป็น "logger.plist"

จากเชลล์คุณสามารถใช้คำสั่งlaunchctlเพื่อเปิดใช้งาน logger.plist โดยเรียกใช้:

$ launchctl load ~/Library/LaunchAgents/logger.plist

กำลังตรวจสอบโฟลเดอร์เดสก์ท็อปอยู่ในขณะนี้ ทุกครั้งที่มีการเปลี่ยนแปลงคุณควรเห็นผลลัพธ์ใน system.log (ใช้ Console.app) ในการปิดการใช้งานตัวบันทึกให้เรียกใช้:

$ launchctl unload ~/Library/LaunchAgents/logger.plist

ไฟล์การกำหนดค่าด้านบนใช้WatchPathsตัวเลือก หรือคุณสามารถใช้ QueueDirectoriesตัวเลือก ดูที่หน้า man launchdสำหรับข้อมูลเพิ่มเติม


1
มีวิธีให้ตรวจสอบการเปลี่ยนแปลงในเนื้อหาของไฟล์รวมถึงเส้นทางของไฟล์หรือไม่?
บแคม

2
ฉันไม่คิดอย่างนั้น คุณสามารถใช้opensnoopเพื่อจุดประสงค์นั้น
sakra

1
ฉันได้รับการทำงาน แต่เมื่อฉันสลับ/usr/bin/loggerกับสคริปต์ Bash ของฉันและลบ"<string>path modified</strong>"รายการฉันไม่สามารถหาวิธีใด ๆ ที่สคริปต์ทุบตีของฉันจะรู้ว่าไฟล์ใดบนเดสก์ท็อปของฉันถูกแก้ไข - เพียงแค่เหตุการณ์เกิดขึ้น ฉันพยายามมองหาที่$0, $1และมีเพียงชื่อสคริปต์ของตัวเองสังเกตผ่านไป
Volomike

นอกจากนี้สิ่งนี้จะเข้าสู่ลูปเมื่อตรวจพบการเปลี่ยนแปลงแทนที่จะเปิดตัว (และหยุด) เมื่อตรวจพบการเปลี่ยนแปลงหรือไม่ ฉันอยากให้มันทำงานได้ตามต้องการไม่ใช่ทำงานเป็นวงวนบอกฉันว่าอย่างเช่นเมื่อ 2 วันก่อนมีบางอย่างเปลี่ยนไปบนเดสก์ท็อปของฉันเขียนว่าในบันทึกซ้ำแล้วซ้ำอีก ดังนั้นเราจำเป็นต้องใช้ตัวเลือกช่วงเวลาบางอย่างในโปรแกรมนี้หรือไม่?
Volomike

การทำงานและการอธิบายที่ยอดเยี่ยม
ChenSmile

37

Watchmanของ Facebook มีให้ผ่าน Homebrew ก็ดูดีเช่นกัน มันยังรองรับการกรอง:

สองบรรทัดนี้สร้างการเฝ้าดูในไดเรกทอรีต้นทางจากนั้นตั้งค่าทริกเกอร์ชื่อ "buildme" ที่จะเรียกใช้เครื่องมือชื่อ "minify-css" ทุกครั้งที่มีการเปลี่ยนไฟล์ CSS เครื่องมือจะถูกส่งผ่านรายการของชื่อไฟล์ที่เปลี่ยนแปลง

$ watchman watch ~/src

$ watchman -- trigger ~/src buildme '*.css' -- minify-css

ขอให้สังเกตว่าเส้นทางจะต้องสมบูรณ์


1
นี่คือเครื่องมือที่ดีที่สุด
BentOnCoding

1
นี่เป็นโปรแกรมเล็ก ๆ ที่ดีมาก: เอกสารนั้นยอดเยี่ยมไม่เปิดลูปไม่สิ้นสุด (ซึ่งเป็นสิ่งที่ fswatch ดูเหมือนว่าจะทำ) และมันจะจดจำนาฬิกาที่คุณสร้างขึ้นหลังจากรีบูตและเริ่มอัตโนมัติอีกครั้ง
แบรด

21

คุณอาจต้องการที่จะดูที่ (และอาจจะขยาย) kqwaitเครื่องมือเล็ก ขณะนี้มันตั้งอยู่รอบ ๆ และรอการเขียนเหตุการณ์ในไฟล์เดียว แต่สถาปัตยกรรมkqueueอนุญาตให้มีการซ้อนเหตุการณ์แบบลำดับชั้น ...


ทำงานได้ไกลกับสิงโตภูเขา ดีมาก!
สกอตต์

ดังนั้นนี่มันยอดเยี่ยมจริง ๆ ฉันวิ่งเข้าไปในปัญหาเล็กน้อยด้วยfswatch(ซึ่งก็ดีเช่นกันเนื่องจากมันห่อหุ้มเบา ๆ มันยังสามารถปรับเปลี่ยนเพื่อทำสิ่งที่เหมาะสมฉันแน่ใจ) ที่มันจะยิงเมื่อทำงานสิ่งที่ต้องการgit status(ซึ่งจริง ๆ แล้วทำงานทุกครั้ง zsh มีการแสดงพรอมต์บนเครื่องของฉัน ... ) ซึ่งอันที่จริงแล้วสกรูขึ้นสคริปต์ที่ซับซ้อนฉันมีโดยการสร้างห่วงข้อเสนอแนะที่ไม่มีที่สิ้นสุด kqwait git statusแต่ให้ข้อมูลเกี่ยวกับแฟ้มเปลี่ยนแปลงและไม่สะดุด ฉันต้องการมันในการเขียน
Steven Lu

2
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
Joshua Cook

15

watchdogเป็น python API ข้ามแพลตฟอร์มสำหรับการดูไฟล์ / ไดเรกทอรีและมีเครื่องมือ "เทคนิค" ในตัวที่ช่วยให้คุณสามารถเรียกการกระทำ (รวมถึงคำสั่งเชลล์) เมื่อมีเหตุการณ์เกิดขึ้น (รวมถึงไฟล์ที่เพิ่มใหม่ไฟล์ที่ถูกลบและไฟล์ที่เปลี่ยนแปลง)


7

นี่เป็นเพียงการพูดถึงentrเป็นทางเลือกบน OSX เพื่อเรียกใช้คำสั่งโดยพลการเมื่อมีการเปลี่ยนแปลงไฟล์ ฉันคิดว่ามันง่ายและมีประโยชน์



3

แก้ไข: fswถูกรวมเข้าfswatchด้วยกัน ในคำตอบนี้อ้างอิงถึงตอนนี้ควรอ่านfswfswatch

ฉันเขียนการfswatchแทนที่ใน C ++ ที่เรียกว่าfswมีการปรับปรุงหลายประการ:

  • เป็นโครงการสร้างระบบ GNU ซึ่งสร้างบนแพลตฟอร์มที่รองรับ (OS X v.> = 10.6) ด้วย

    ./configure && make && sudo make install
    
  • หลายเส้นทางสามารถส่งผ่านเป็นอาร์กิวเมนต์ที่แตกต่างกัน:

    fsw file-0 ... file-n 
    
  • มันทิ้งบันทึกรายละเอียดพร้อมข้อมูลเหตุการณ์ทั้งหมดเช่น:

    Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile 
    
  • เอาต์พุตแยกวิเคราะห์ได้ง่ายเพื่อให้fswสามารถส่งเอาต์พุตไปยังกระบวนการอื่นได้

  • -l, --latencyแฝงสามารถปรับแต่งด้วย
  • -n, --numericธงเหตุการณ์ตัวเลขสามารถเขียนแทนคนที่เป็นข้อความด้วย
  • รูปแบบเวลาที่สามารถปรับแต่งโดยใช้สายรูปแบบด้วยstrftime-t, --time-format
  • เวลาที่สามารถเป็นท้องถิ่นเวลาของเครื่อง (ค่าเริ่มต้น) หรือเวลา UTC -u, --utc-timeกับ

รับ fsw:

fswถูกโฮสต์ใน GitHubและสามารถทำการโคลนที่เก็บได้:

    git clone https://github.com/emcrisostomo/fsw

ติดตั้ง fsw:

fsw สามารถติดตั้งได้โดยใช้คำสั่งต่อไปนี้:

    ./configure && make && sudo make install

ข้อมูลเพิ่มเติม:

ฉันยังเขียนโพสต์บล็อกเบื้องต้นที่คุณสามารถหาตัวอย่างสองสามตัวอย่างเกี่ยวกับวิธีการfswทำงาน


2

การดำเนินการกับโฟลเดอร์ Apple OSX ช่วยให้คุณสามารถทำงานอัตโนมัติตามการดำเนินการในโฟลเดอร์


9
ใช่ฉันรู้ว่าฉันพยายามใช้หลายครั้งไม่เคยประสบความสำเร็จในการทำงานคุณช่วยยกตัวอย่างให้ฉันได้ไหม
มิ้นต์

1
นั่นคือลิงก์ไม่ใช่คำตอบ
Dan Rosenstark

2

My fork of fswatchให้ฟังก์ชั่นการทำงานที่inotifywait -mมีน้อยกว่าเล็กน้อย (ไม่ต้องรอมากไปกว่านี้ฉันมีปัญหามากขึ้นใน Linux ที่มีinotifywait... ) เอาต์พุตแบบแยกวิเคราะห์ที่เป็นมิตร

มันเป็นการปรับปรุงตามต้นฉบับ fswatchเนื่องจากมันจะส่งเส้นทางที่แท้จริงของไฟล์ที่ถูกเปลี่ยนไปบน STDOUT แทนที่จะต้องการให้คุณจัดเตรียมโปรแกรมที่จะใช้

มันแข็งเป็นรากฐานของชุดสคริปต์ทุบตีที่น่ากลัวที่ฉันใช้เพื่อทำให้สิ่งต่าง ๆ เป็นไปโดยอัตโนมัติ

(นี่เป็นหัวข้อนอก) inotifywaitบน Linux ในทางกลับกันต้องใช้ kludges จำนวนมากที่อยู่ด้านบนของมันและฉันยังไม่ได้คิดวิธีที่ดีในการจัดการแม้ว่าฉันคิดว่าสิ่งที่อยู่บนพื้นฐานnode.jsอาจเป็นตั๋ว


1
ขวาส้อมของ fswatch เป็นเช่นนั้นใน Homebrew หรือไม่
fatuhoku

1
คำตอบคือไม่; แต่พวกเขากำลังทำงานกับมัน หากต้องการติดตั้งอย่างรวดเร็วจริงๆเพียงแค่ brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
fatuhoku

1

ฉันมีรายการสำคัญสำหรับเรื่องนี้และการใช้งานค่อนข้างง่าย

watchfiles <cmd> <paths...>

เพื่อแสดงคำสั่งต่อไปนี้จะสะท้อนHello Worldทุกครั้งที่มีการเปลี่ยนแปลงfile1หรือfile2; และการตรวจสอบช่วงเวลาเริ่มต้นคือ 1 วินาที

watchfiles 'echo Hello World' /path/to/file1 /path/to/file2 

หากฉันต้องการตรวจสอบทุก 5 วินาทีฉันสามารถใช้การ-tตั้งค่าสถานะ

watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2 
  • -vเปิดใช้งานverboseโหมดที่แสดงข้อมูลการดีบัก
  • -qทำให้watchfilesรันอย่างเงียบ ๆ ( #จะปรากฏขึ้นเพื่อให้ผู้ใช้สามารถเห็นโปรแกรมกำลังทำงาน)
  • -qqทำให้watchfilesดำเนินการอย่างเงียบ ๆ อย่างสมบูรณ์
  • -h แสดงให้เห็นถึงความช่วยเหลือและการใช้งาน

https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55


0

ฉันลงเอยด้วยการทำสิ่งนี้เพื่อ macOS ฉันแน่ใจว่านี่แย่มากในหลาย ๆ ด้าน:

#!/bin/sh
# watchAndRun
if [ $# -ne 2 ]; then
    echo "Use like this:"
    echo "   $0 filename-to-watch command-to-run"
    exit 1
fi
if which fswatch >/dev/null; then
    echo "Watching $1 and will run $2"
    while true; do fswatch --one-event $1 >/dev/null && $2; done
else
    echo "You might need to run: brew install fswatch"
fi

ฉันไม่สามารถหาไวยากรณ์ของ fswatch ได้ในขณะนี้ ซึ่งน่ารำคาญและทำให้สคริปต์หยุดยาก
Dan Rosenstark

0

หากคุณต้องการใช้ NodeJS คุณสามารถใช้แพ็คเกจที่เรียกว่าchokidar (หรือchokidar-cliจริง ๆ ) สำหรับการรับชมจากนั้นใช้rsync (รวมอยู่ใน Mac):

คำสั่ง Rsync:

$ rsync -avz --exclude 'some-file' --exclude 'some-dir' './' '/my/destination'

Chokidar cli (ติดตั้งทั่วโลกทาง npm):

chokidar \"**/*\" -c \"your-rsync-command-above\"


-3

นี่คือทางเลือกบรรทัดเดียวแบบง่ายสำหรับผู้ใช้ที่ไม่มีwatchคำสั่งที่ต้องการเรียกใช้คำสั่งทุก 3 วินาที:

while :; do your-command; sleep 3; done

มันเป็นวงที่ไม่มีที่สิ้นสุดซึ่งโดยทั่วไปเหมือนกับการทำสิ่งต่อไปนี้:

watch -n3 your-command


3
สิ่งนี้ไม่เหมือนกับการใช้ไลบรารีที่รับฟังเหตุการณ์จากระบบไฟล์ หากในตัวอย่างของคุณyour-commandใช้ดิสก์ I / O นั่นคือดิสก์ที่รับประกันว่าจะสามารถอ่าน / เขียนได้ทุก 3 วินาทีหรือ 10,800 ครั้งต่อชั่วโมง โดยการใช้เหตุการณ์ระบบไฟล์คุณจะมั่นใจได้ว่า I / O (และการดำเนินการที่มีราคาแพงอื่น ๆ ) จะเกิดขึ้นเฉพาะเมื่อคุณเปลี่ยนไฟล์ (ซึ่งโดยทั่วไปจะใช้เวลาเพียงสองสามครั้งต่อชั่วโมง)
Noah Sussman

จริงและดีที่จะต้องพิจารณา ฉันมักจะต้องทำwatchสิ่งต่าง ๆ เป็นระยะเวลาชั่วคราวเพื่อดูว่ามีอะไรกำลังทำอยู่ ฉันไม่ได้ใช้เทคนิคที่กล่าวถึงในการผลิตแอพหรืออะไรทำนองนั้น ตัวอย่างเช่นฉันต้องการดูความคืบหน้าของddและเทคนิคของฉันทำให้มันเกิดขึ้น (แทนที่your-commandตามความเหมาะสมในการส่งสัญญาณที่เหมาะสมไปdd)
trusktr
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.