Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

Is there a simple way to automatically run a (Terminal) command every time a file is changed in a specific folder?

This should be possible via the command line, or a system built-in application, no third-party applications.

Any ideas?

share|improve this question
    
    
Another dupe? apple.stackexchange.com/questions/6658/… –  user588 Feb 17 '12 at 15:08
add comment

5 Answers

entr(1) is a utility for running commands when files change. It reads a list of file on STDIN and uses kqueue(2) to avoid polling.

Example:

ls my_project/*.html | entr echo "file changed"
share|improve this answer
add comment

Save a property list like this as ~/Library/LaunchAgents/test.plist:

<?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>test</string>
    <key>ProgramArguments</key>
    <array>
        <string>say</string>
        <string>yy</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>~/Desktop/</string>
    </array>
</dict>
</plist>

The agent can be loaded with launchctl load ~/Library/LaunchAgents/test.plist or by logging out and back in. Applying changes requires unloading and loading the plist.

Tilde expansion (~/) works in WatchPaths by default. EnableGlobbing adds wildcard and tilde expansion for ProgramArguments, but it doesn't affect Program or WatchPaths.

If a watched file is modified within ten seconds from the last invocation, a message like this is added to system.log:

com.apple.launchd.peruser.501[146]: (test) Throttling respawn: Will start in 7 seconds

One way to get rid of the messages is to add something like sleep 10 to the end of scripts. Setting ThrottleInterval to 10 doesn't help.

Changes in subfolders of watched folders aren't detected.

See man launchd and man launchd.plist for more information.

share|improve this answer
add comment

You could use Folder Actions, which lets you execute (Automator) scripts whenever contents in a folder change. As far as I know, Automator has a template that lets you easily create a new folder action and attach it to the desired folder. And by adding a "Run Shell Script" action, you should just get the desired effect.

share|improve this answer
3  
Thanks, but it appears that "Folder Actions" are only triggered when a file is added to the folder, not when an existing file is checked. –  Louis Bataillard Feb 17 '12 at 15:06
add comment

Automator has a type of workflow called a "Folder Action" which automatically runs when something is added to a folder. Create one, then use the action "Run Shell Script."

share|improve this answer
2  
Thanks, but it appears that "Folder Actions" are only triggered when a file is added to the folder, not when an existing file is checked. –  Louis Bataillard Feb 17 '12 at 15:06
    
Oh, okay. Sorry. –  timothymh Feb 17 '12 at 21:05
add comment

You might want to try something like this:

touch /tmp/dirb.tmp
while true do 
  ls /thedirtocheck > /tmp/dira.tmp 
  diff /tmp/dira.tmp /tmp/dirb.tmp || echo "something changed" 
  cp /tmp/dira.tmp /tmp/dirb.tmp 
  sleep 100 
done
share|improve this answer
    
You need at least ls -l to catch file changes as well. –  patrix Feb 17 '12 at 12:15
    
right.... missed that –  Holger von Ameln Feb 17 '12 at 17:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.