21

I used to use fswatch v0.0.2 like so (in this instance to run django test suit when a file changed)

$>fswatch . 'python manage.py test'

this works fine.

I wanted to exclude some files that were causing the test to run more than once per save (Sublime text was saving a .tmp file, and I suspect .pyc files were also causing this)

So I upgraded fswatch to enable the -e mode.

However the way fswatch has changed which is causing me troubles - it now accepts a pipe argument like so:

$>fswatch . | xargs -n1 program

I can't figure out how to pass in arguments to the program here. e.g. this does not work:

$>fswatch . | xargs -n1 python manage.py test

nor does this:

$>fswatch . | xargs -n1 'python manage.py test'

how can I do this without packaging up my command in a bash script?

reevesy
  • 3,452
  • 1
  • 26
  • 23
Guy Bowden
  • 4,997
  • 5
  • 38
  • 58

2 Answers2

26

fswatch documentation (either the Texinfo manual, or the wiki, or README) have examples of how this is done:

$ fswatch [opts] -0 -o path ... | xargs -0 -n1 -I{} your full command goes here

Pitfalls:

  • xargs -0, fswatch -0: use it to make sure paths with newlines are interpreted correctly.
  • fswatch -o: use it to have fswatch "bubble" all the events in the set into a single one printing only the number of records in the set.
  • -I{}: specifying a placeholder is the trick you missed for xargs interpreting correctly your command arguments in those cases where you do not want the record (in this case, since -o was used, the number of records in the set) to be passed down to the command being executed.
Grisha Levit
  • 8,194
  • 2
  • 38
  • 53
Enrico M. Crisostomo
  • 1,653
  • 1
  • 17
  • 26
  • have marked this as correct as it answers the crux of my initial question - using xargs without passing the output as arguments to the command to be run. – Guy Bowden Sep 08 '14 at 10:48
  • 1
    I think the "-o" option should go with fswatch, not xargs. – Anna B Dec 30 '20 at 22:28
26

Alternative answer not fighting xargs' default reason for being - passing on the output as arguments to the command to be run.

fswatch . | (while read; do python manage.py test; done)

Which is still a bit wordy/syntaxy, so I have created a super simple bash script fswatch-do that simplifies things for me:

#!/bin/bash  
(while read; do "$@"; done)

usage:

fswatch -r -o -e 'pyc' somepath | fswatch-do python manage.py test someapp.SomeAppTestCase

Grisha Levit
  • 8,194
  • 2
  • 38
  • 53
Guy Bowden
  • 4,997
  • 5
  • 38
  • 58
  • If being run within a Bourne shell (as can happen in a subprocess invocation depending on one's config) the `read` command will need a dummy argument. – user650881 Mar 26 '20 at 01:09
  • 1
    There is no need to wrap the last part of the pipeline in parantheses to make a subshell. – Grisha Levit Feb 27 '21 at 03:14