# Word Count Script requested

**URL:** <https://forum.beeminder.com/t/word-count-script-requested/963>\
**Category:** Tech\
**Created:** [July 16, 2015, 4:15pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963 "2015-07-16T16:15:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![oldmannick](https://avatars.discourse-cdn.com/v4/letter/o/ad7895/32.png) [@oldmannick](https://forum.beeminder.com/u/oldmannick)\
**Post date:** [July 16, 2015, 4:15pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/1 "2015-07-16T16:15:53Z")

</div>

Hey guys,

I currently use Beeminder’s draft integration to beemind daily word count. I’d like to be able to write in plain text files on my computer so I don’t need to copy paste from Draft all the time.

Does anyone have a short shell script that I can run in Hazel on a designated writing folder that’ll send the word count to Beeminder?

---

<div class="post-metadata">

**Author:** ![philip](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/philip/32/1505_2.png) [@philip](https://forum.beeminder.com/u/philip)\
**Post date:** [July 16, 2015, 7:29pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/2 "2015-07-16T19:29:21Z")

</div>

I use Hazel to [merge my TagTime logs](http://forum.beeminder.com/t/a-good-approach-to-merge-tagtime-logs/289/8) and update the relevant Beeminder goals. (screenshots in the linked forum post!)

That’s a good idea, having Hazel upload word counts. One thing to be mildly careful of is that our Draft integration gives you credit for editing (i.e. deleting) words. The easy shell script version is only going to report the current word count on existing files…

For updating Beeminder, you’ll want to grab a copy of [@bkam’s bmndr script](https://github.com/lydgate/bmndr) or [my forked version](https://github.com/pjjh/bmndr). Then you can run something like this to update mygoal with the wordcount and a comment of the filename:

> `bmndr mygoal $(cat "$1" | wc -w) "$1"`

There’s obviously a relationship between your Hazel setup and how you configure your Beeminder goal. What did you have in mind?

* * *

_For those playing along at home, [Hazel](http://www.noodlesoft.com/hazel.php) is an awesome and flexible Mac automation utility. Rules watch for changes in files or folders, and trigger a wide variety of actions, including arbitrary scripts._

---

<div class="post-metadata">

**Author:** ![oldmannick](https://avatars.discourse-cdn.com/v4/letter/o/ad7895/32.png) [@oldmannick](https://forum.beeminder.com/u/oldmannick)\
**Post date:** [July 18, 2015, 7:11pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/3 "2015-07-18T19:11:02Z")

</div>

I actually only care about total word count, not words edited.

My goal is be able to just automatically run word count on a file whenever I add that file to my writing folder, and then send that total to update Beeminder.

---

<div class="post-metadata">

**Author:** ![philip](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/philip/32/1505_2.png) [@philip](https://forum.beeminder.com/u/philip)\
**Post date:** [July 18, 2015, 7:33pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/4 "2015-07-18T19:33:03Z")

</div>

Excellent. In that case, the above will do the trick.

Even with a dedicated count-these-files writing folder, you’ll probably want to build some safety measures into your Hazel file-matching rules, like

- not if modified in the last X minutes
- only if modified in the last day

If you create an ordinary **do more** Beeminder goal, then a script similar to this should work fine:

```
bmndr mygoal $(cat "$1" | wc -w) "$1"

```

If you keep modifying the files in place, Hazel will keep adding **new** datapoints to your goal, each with the current total word count, which is almost certainly not what you want. If you only ever copy across writing that is ‘done’, it shouldn’t be an issue. If that’s where you keep your work-in-progress, you’ll have to come up with a counting scheme that you’re happy with.

Premium subscribers could do something fancy with the **[aggregation](http://forum.beeminder.com/t/documentation-of-aggregation-methods-would-be-nice/549/4)** settings, but there’s no single straightforward generic answer.

Let me know how it goes.

---

<div class="post-metadata">

**Author:** ![insti](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/insti/32/545_2.png) [@insti](https://forum.beeminder.com/u/insti)\
**Post date:** [July 18, 2015, 9:11pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/5 "2015-07-18T21:11:08Z")

</div>

You could maybe use an **odometer** goal and wordcount all the files in the directory every time.

---

<div class="post-metadata">

**Author:** ![philip](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/philip/32/1505_2.png) [@philip](https://forum.beeminder.com/u/philip)\
**Post date:** [July 18, 2015, 9:43pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/6 "2015-07-18T21:43:47Z")

</div>

Indeed. That’s why the goal and the hazel need to match the workflow.

An odometer goal has an equal & opposite problem. Can’t delete or move files out…

---

<div class="post-metadata">

**Author:** ![oldmannick](https://avatars.discourse-cdn.com/v4/letter/o/ad7895/32.png) [@oldmannick](https://forum.beeminder.com/u/oldmannick)\
**Post date:** [July 23, 2015, 10:48pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/7 "2015-07-23T22:48:39Z")

</div>

I get the issue of `command not found: bmdr` when I try to run this script  
in the terminal. I have the correct api keys, so I’m wondering why my shell  
does not recognize the command.

Regards,  
Alok Singh

---

<div class="post-metadata">

**Author:** ![philip](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/philip/32/1505_2.png) [@philip](https://forum.beeminder.com/u/philip)\
**Post date:** [July 23, 2015, 11:53pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/8 "2015-07-23T23:53:13Z")

</div>

Hi Alok! I’m answering this assuming that you’re new to using Terminal and command line. Apologies if that’s not related to this particular confusion. You could do worse than buying the relevant [take control guide](https://www.takecontrolbooks.com/command-line) as an introduction to the command line. But here are a couple ideas that might get you unstuck:

Loosely speaking, any script needs to be a) executable and b) located by the thing that’s calling it.

The first can be fixed by running this in the directory that you’ve saved the bmndr script

```
chmod a+x bmndr

```

For the second, you could either move the script to somewhere on your ‘path’, or explicitly tell Hazel where you’ve put it, as in something like:

```
/Users/philip/bmndr mygoal $(cat "$1" | wc -w) "$1"

```

Or to test from the terminal itself, try:

```
./bmndr
```

---

<div class="post-metadata">

**Author:** ![oldmannick](https://avatars.discourse-cdn.com/v4/letter/o/ad7895/32.png) [@oldmannick](https://forum.beeminder.com/u/oldmannick)\
**Post date:** [July 24, 2015, 3:05am UTC](https://forum.beeminder.com/t/word-count-script-requested/963/9 "2015-07-24T03:05:02Z")

</div>

I’m not new to the terminal.  
I already ran `chmod` to no avail. Running `./bmndr` gives the following output.

`File "./bmndr", line 60, in <module> data = loads(urlopen('https://www.beeminder.com/api/v1/users/me/goals.json?auth_token=%s&filter=%s' % (auth_token,burner)).read().decode('utf-8')) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 87, in urlopen return opener.open(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 208, in open return getattr(self, name)(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 451, in open_https return self.http_error(url, fp, errcode, errmsg, headers) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 372, in http_error result = method(url, fp, errcode, errmsg, headers) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 683, in http_error_401 errcode, errmsg, headers) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 381, in http_error_default raise IOError, ('http error', errcode, errmsg, headers) IOError: ('http error', 401, 'Unauthorized', <httplib.HTTPMessage instance at 0x10e411d88>)`

---

<div class="post-metadata">

**Author:** ![philip](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/philip/32/1505_2.png) [@philip](https://forum.beeminder.com/u/philip)\
**Post date:** [July 24, 2015, 1:13pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/10 "2015-07-24T13:13:42Z")

</div>

That looks nothing like ‘`command not found`’… 🙂

(Re-reading your initial error report, it says ‘`bmdr`’ instead of ‘`bmndr`’, which is a typo in one place or another.)

Line 60 of my `bmndr` script contains the error “`Missing or malformed configuration file.`”, which is highly suggestive of what might have gone wrong (though I’m a python ignoramus, so can’t begin to guess why that message doesn’t appear in your stack trace).

I seem to recall that one of the differences between my fork and lydgate’s original has to do with the format of the config file, because I use the same file from perl and other scripts.

---

<div class="post-metadata">

**Author:** ![insti](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/insti/32/545_2.png) [@insti](https://forum.beeminder.com/u/insti)\
**Post date:** [July 24, 2015, 8:02pm UTC](https://forum.beeminder.com/t/word-count-script-requested/963/11 "2015-07-24T20:02:26Z")

</div>

The last line shows the problem you need to fix:

> [@oldmannick](#):
>
> IOError: ( **‘http error’, 401, ‘Unauthorized’** , \<httplib.HTTPMessage instance at 0x10e411d88\>)

I’m guessing your auth token is not set correctly.  
Did you copy the auth token from [beeminder](https://www.beeminder.com/settings/advanced_settings) into the correct place in your config file?
