Bash Script to Generate .css from .less Files Using lessc
bash, less, linux
Solution
You've got all the ingredients. You just need the recipe. :-)
And there are multiple recipes.
Normally, you can use `find`'s `-exec` option to execute things based on what it finds. However, you're limited in what you can name things. For example, if you were to use this:
find . -name \*.less -exec lessc {} ../css/{}.css
you would create files in a css directory in the parent from where find is running, and files would be named things like a.less.css, b.less.css, etc. That's not good. You'd need to embed `dirname` and such into your command, and then things get impossible to manage, with too many quotes and backslashes.
When I have to do pattern-matting AND changes like this, I often resort to pipes. Here's what I'd do:
find . -name \*.less -print | \
sed -rne 's:(.*)/less/([^/]+).less$:lessc & > \1/css/\2.css:p'
The `find` gets your files, as you'd expect. Then the `sed` script turns them into command lines. The output of this is a collection of `lessc` command lines which you can simply pipe into `sh` once you've verified that they look right.
Here are the results.
Before:
[ghoti@pc ~/tmp1]$ find . -type f -print
./whatever/less/c.less
./whatever/less/d.less
./less/a.less
./less/b.less
[ghoti@pc ~/tmp1]$
Then the test run:
[ghoti@pc ~/tmp1]$ find . -name \*.less -print | sed -rne 's:(.*)/less/([^/]+).less$:cat & > \1/css/\2.css:p'
cat ./whatever/less/c.less > ./whatever/css/c.css
cat ./whatever/less/d.less > ./whatever/css/d.css
cat ./less/a.less > ./css/a.css
cat ./less/b.less > ./css/b.css
[ghoti@pc ~/tmp1]$
Then the final run, and results.
[ghoti@pc ~/tmp1]$ find . -name \*.less -print | sed -rne 's:(.*)/less/([^/]+).less$:cat & > \1/css/\2.css:p' | sh
[ghoti@pc ~/tmp1]$ find . -type f -print
./css/b.css
./css/a.css
./whatever/less/c.less
./whatever/less/d.less
./whatever/css/d.css
./whatever/css/c.css
./less/a.less
./less/b.less
[ghoti@pc ~/tmp1]$
For my test, I replaced `lessc` with `cat`, since less isn't installed on my workstation.
Note that this will only work with simple filenames like the ones in your example. If you have spaces or possibly other "special" characters, it will break.
Problem
I'm looking to write a bash script that will recursively find all `.less` files in a directory and create a `.css` file with the same name in a parent `css` directory using `lessc`. Visually it looks like this. Before: ``` /css /less a.less b.less /whatever /css /less c.less d.less ``` After: ``` /css a.css b.css /less a.less b.less /whatever /css c.css d.css /less c.less d.less ``` What I've been able to figure out so far is that I can find all the files using: ``` find . -name *.less ``` And I can generate individual files using: ``` lessc foo.less > ../css/foo.css ``` My problem comes trying to pipe the results of the `find` into `lessc`. Per this question I can see how the results of `find` can be piped into `cat`, but the same approach isn't working for me with `lessc`. In general I'm just having trouble putting the pieces together. Any help would be appreciated. Thanks. Edit This is what worked for me. Thanks @ghoti! ``` find . -name \*.less -print | sed -rne 's:(.*)/less/([^/]+).less$:lessc & > \1/css/\2.css:p' | sh ```