มีคำสั่งเช่น "ดู" หรือ "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.