Есть ли такая команда, как «смотреть» или «inotifywait» на Mac?


287

Я хочу посмотреть папку на моем Mac (Snow Leopard), а затем выполнить скрипт (присвоив ему имя файла, который был только что перемещен в папку (как параметр ... x.sh "filename")).

У меня есть сценарий, написанный на bash (x.sh), который будет перемещать некоторые файлы и другие данные на входе $ 1. Мне просто нужен OSX, чтобы дать мне имя файла, когда новые файлы / папки перемещаются / создаются в каталог.

Любая такая команда?


1
Вы должны спросить, как DropBox делает это, так как, по-видимому, они перепробовали все доступные варианты.
Джефф Берджес

2
@JeffBurdges Я не уверен, что это будет легко. Однако я бы сказал, что после просмотра справочника FSEvents от Apple было бы очень глупо, если бы Dropbox не использовал это. fswatchUtil представлен как ответ ниже делает фактически использовать этот метод.
Стивен Лу

Ответы:


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

По состоянию на 12.09.13 он был добавлен обратно в доморощенный - ууу! Итак, обновите список формул ( brew update), а затем все, что вам нужно сделать, это:

brew install fswatch

Установка без доморощенного

Введите эти команды в Terminal.app

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

Если у вас нет cкомпилятора в вашей системе, вам может понадобиться установить инструменты командной строки Xcode или Xcode - и то, и другое бесплатно. Тем не менее, если это так, вам, вероятно, следует просто проверить доморощенный .

Дополнительные параметры для 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.

Ваши инструкции или установка без доморощенного, похоже, больше не работают. makeвыдает ошибку о том, что не нашел make-файл К счастью, 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для NULL. Этот работает для меня меньше сборник
болдник

95

Вы можете использовать launchd для этой цели. Launchd может быть настроен на автоматический запуск программы при изменении пути к файлу.

Например, следующий лист запуска configd запустит программу /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 в папке «Библиотека» как «logger.plist».

Из оболочки вы можете использовать команду launchctlдля активации logger.plist, выполнив:

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

Папка рабочего стола теперь отслеживается. Каждый раз, когда он изменяется, вы должны видеть вывод в system.log (используйте Console.app). Чтобы отключить logger.plist, запустите:

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

Файл конфигурации выше использует эту WatchPathsопцию. В качестве альтернативы вы также можете использовать эту QueueDirectoriesопцию. Смотрите mand- страницу launchd для получения дополнительной информации.


1
Есть ли способ заставить его отслеживать изменения содержимого файла, а также путь к файлу?
Cam

2
Я так не думаю. Вы можете использовать opensnoop для этой цели.
Сакра

1
Я заставил это работать, но затем, когда я переключился /usr/bin/loggerсо своим сценарием Bash и удалил "<string>path modified</strong>"запись, я не смог найти способ для моего сценария bash узнать, какой файл на моем рабочем столе был изменен - ​​только что произошло событие. Я попытался посмотреть $0, $1и получил только имя сценария, отметив, что передано ему.
Volomike

Кроме того, входит ли эта вещь в цикл, когда обнаруживает изменение, а не только запускает (и останавливает), когда обнаруживает изменение? Я предпочел бы, чтобы это работало по требованию, а не продолжал работать в цикле, говоря мне, что, например, 2 дня назад что-то изменилось на моем рабочем столе, записывая это в журнал снова и снова. Итак, нам нужно использовать какой-то интервал в этом списке?
Volomike

Отличная работа и объяснение
ChenSmile

37

Сторож 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. Мне действительно нужно, чтобы выстрел, хотя.
Стивен Лу

2
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
Джошуа Кук

15

watchdog - это кроссплатформенный Python API для просмотра файлов / каталогов, и он имеет встроенный инструмент «хитрости», который позволяет запускать действия (включая команды оболочки) при возникновении событий (включая новый добавленный файл, удаленный файл и измененный файл).


7

Это просто упомянуть entr как альтернативу OSX для запуска произвольных команд при изменении файлов. Я нахожу это простым и полезным.



3

Изменить: fsw был объединен в fswatch. В этом ответе любая ссылка на fswтеперь должна читаться fswatch.

Я написал 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
Это ссылка, а не ответ
Дэн Розенстарк

2

Моя ветвь fswatch предоставляет функциональность inotifywait -mс немного меньшим (не подождите, больше! У меня намного больше проблем с Linux с inotifywait...) дружественным для синтаксического анализа выводом.

Это улучшение по сравнению с оригиналом, fswatchпоскольку он отправляет фактический путь измененного файла через STDOUT, а не требует от вас предоставления программы, которую он разветвляет.

Это было прочное основание серии страшных скриптов bash, которые я использую для автоматизации вещей.

(это не по теме) inotifywaitв Linux, с другой стороны, требуется много кладжей поверх него, и я до сих пор не нашел хорошего способа управления им, хотя я думаю, что что-то, основанное на этом, node.jsможет быть билетом.


1
Правильно, вилка fswatch. Является ли, что на Homebrew?
фатухоку

1
Ответ - нет; но они работают над этим . Установить его действительно быстро просто brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
фатухоку

1

У меня есть GIST для этого, и использование довольно просто

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 без времени. Что раздражает и делает сценарий трудно остановить.
Дэн Розенстарк

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выполняется дисковый ввод / вывод, то это гарантированное чтение / запись диска каждые 3 секунды - или 10 800 раз в час. Используя события файловой системы, вы гарантируете, что ввод-вывод (и другие дорогостоящие операции) будут происходить только при изменении файла (что обычно происходит всего пару раз в час.)
Ноа Суссман

Правда и хорошо, чтобы рассмотреть. Мне обычно нужно что- watchто временное, чтобы посмотреть, что что-то делает. Я не использую свою упомянутую технику для производственных приложений или чего-то подобного. Например, я хотел бы видеть прогресс dd, и моя техника делает это возможным (заменив your-commandпри необходимости, чтобы отправить соответствующий сигнал dd).
trusktr
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.