53

I have a directory full of less css files. What is the best way to compile them to normal css? (for deployment)

Id like to run a command as follows:

lessc -r less/ css/

where lessc is the less compiler (installed via node package manager)

Timothy Strimple
  • 22,920
  • 6
  • 69
  • 76
tallowen
  • 4,198
  • 7
  • 27
  • 35
  • Use @import on the main css file to import them together and use [Prepros App](http://alphapixels.com/prepros) That can compile less, sass, stylus, jade, haml and markdown on the fly with live browser reload. – Subash Pathak May 02 '13 at 02:54
  • 2
    on windows you can use [winless](http://winless.org/) ;) – AgelessEssence Apr 25 '13 at 13:16
  • Use Guard. https://github.com/mloberg/guard-less (this fork contains an up-to-date gem dependency versions) – elado Jun 10 '13 at 17:48
  • If someone is looking to compile all the LESS file into a folder tree in Windows. In the following my solution using a batch file in WIndows: File compile-less.bat: `@echo cd ".\pages" for /r %%i in (*.less) do call lessc --clean-css "%%~i" "%%~dpni.min.css" cd ..` All the less file in the folder pages and its subfolders will be compiled. – DAme Mar 27 '19 at 14:03

14 Answers14

75

The way to do this is what bootstrap does - have a file which imports all the others and compile that.

@import "variables.less"; 
@import "mixins.less";
Damian
  • 2,588
  • 23
  • 19
  • 6
    The original question (and what I have just been trying to do) talks about how to monitor whole directories and generate multiple .less files. So whilst this answer doesn't explicitly answer that (and the lessc tool doesn't seem to handle it either) I gave up and built everything into an all.css file using this approach, and now agree this is the best option :-) – Alex York Mar 24 '15 at 14:54
24

You can use the following bash one-liner to compile and all less files in a directory and its subdirectories into a single css file "combined.css":

$ find less_directory/ -name '*.less' -exec lessc {} \; > combined.css

Or minified for production:

$ find less_directory/ -name '*.less' -exec lessc -x {} \; > combined.css
Dan Noble
  • 733
  • 6
  • 13
15

If you want compile multiple less files into multiple css files try this one-liner bash script:

for file in *.less; do lessc -x --yui-compress -O2 --strict-imports $file `basename $file`.css ; done

You will get a list of .less.css files after run the command.

PS: It addittionaly optimizes (-O2) at maximum, compress (-x) and minifies with YUI Compressor (--yui-compress) with strict import evaluation (--strict-imports).

EDITED: For new YUI Compressor versions skip -02 and --yui-compress deprecated, so:

for file in *.less; do lessc -x --strict-imports $file `basename $file`.css ; done
shakaran
  • 10,612
  • 2
  • 29
  • 46
  • This is the answer I was looking for - though for modern versions of lessc `-O2` and `--yui-compress` are both deprecated, so you should skip them. – Zack Jul 29 '14 at 03:57
  • Am I the only one for whom `basename` doesn't strip `.less`? I replaced `basename $file` with `basename $file | cut -f 1 -d '.'`. – MuffinTheMan Nov 19 '19 at 20:54
  • Actually, it seems I only needed to replace `basename $file` with `basename $file .less`. I would edit the answer; but I'm not confident enough about this. Can someone confirm that this isn't just me and then edit the answer, if not just me? – MuffinTheMan Nov 19 '19 at 23:07
  • It's not just you @MuffinTheMan – Eran Goldin Aug 24 '22 at 14:38
6

This bash script works for me:

find "$PWD" -name '*.less' | while read line; do
    REPLACE=`echo $line | sed "s|\.less|\.css|"`

    # echo "$line --> $REPLACE"
    (lessc "$line" "$REPLACE" &)
done
iloveitaly
  • 2,053
  • 22
  • 21
5

I made this VERY simple bash script to compile all LESS files in a directory to CSS

#/bin/bash
echo "Compiling all LESS files to CSS"
for file in *.less
do
    FROM=$file
    TO=${file/.*/.css}
    echo "$FROM --> $TO"
    lessc $FROM $TO
done
Sam Stern
  • 24,624
  • 13
  • 93
  • 124
  • Very helpful script, this helped me a lot! Thank you. For others, just run this script in the same directory as your .less files and it will convert each one into separate .css files. Exactly what I needed. Saves tons of time! What I did was type 'vi compileless.sh', and copied his script in there, and you simply run it via console as sh compileless. If you are not familiar with the VIM editor, use 'i' to insert his text in, then press escape key and then press the ':' key and s, press enter. This will save, then :q to quit. – Joseph Astrahan Jul 09 '15 at 20:17
4

I just made the script on top of @iloveitaly's work:

#!/bin/bash
# file name: lesscdir

if [[ -z $1 || -z $2 ]];then
    echo 'both arguments are needed'
    exit
fi

find $1 -name '*.less' -printf '%P\n' | while read name; do
    FROM=$(echo $1'/'$name)
    TO=$(echo $2'/'$name | sed "s|\.less|\.css|")
    TO_DIRNAME=$(dirname $TO)
    if [ ! -e $TO_DIRNAME ];then
        mkdir -p $TO_DIRNAME
    fi
    echo 'Compiling' $FROM '->' $TO
    lessc $FROM $TO
done

and then:

$ chmod +x lesscdir
$ sudo ln -s $(readlink -f lesscdir) /usr/local/bin/

Although I like python the best and solve most problems with it, it's still very happy to use bash in linux environment.

Reorx
  • 2,801
  • 2
  • 24
  • 29
3

I have written a hackish script that solves the problem:

#!/usr/bin/env python


#This is responsible for "compiling" less.css files to regular css files for production. It also minifies the css at the same time. 

#Usage: give it a start directory as the first parameter and an end directory as the second parameter. It will recursivly run the appropriate command for all css files in the first subdirectory.


import os
import sys
import re
if len(sys.argv) < 3:
    sys.exit('ERROR: Too many paths!! No less css compiled')
if len(sys.argv) > 3:
    sys.exit('ERROR: Not enough paths!! No less css compiled')

start_dir=os.path.join(os.getcwd(),sys.argv[1])
end_dir=os.path.join(os.getcwd(),sys.argv[2])
pattern=r'\.css$'
pattern=re.compile(pattern)

files_compiled=0

def copy_files(start, end, add=''):
    global files_compiled
    try:
      os.mkdir(end)
    except:
      pass
    for folder in get_immediate_subdirectories(start):
      copy_files(os.path.join(start,folder), os.path.join(end+folder), add+folder+'/')
    for less in os.listdir(start):
      if pattern.search(less):
        os.system('lessc -x %s > %s'%(start+less,end+less))
        print add+less
        files_compiled=files_compiled+1

def get_immediate_subdirectories(dir):
    return [name for name in os.listdir(dir)
            if os.path.isdir(os.path.join(dir, name))]

Ideally there is a better solution.

tallowen
  • 4,198
  • 7
  • 27
  • 35
2

Based shakaran's answer, but instead of .less.css files, it creates .css files (don't use less in the filename, well only in the extension that is):

for file in *.less; do lessc -x --strict-imports $file `basename $file | sed -e "s/less/css/"` ; done
2

Just found an awesome npm module to do that ! :)

Install it:

$ npm install [-g] lessc-each

Run it:

$ lessc-each  ‹dir1›  ‹dir2›

Where ‹dir1› is the directory of Less files to compile, and ‹dir2› is the directory for output files. If ‹dir2› does not exist, it will automatically be created. Both directories must be relative to the current path of the command line.

1

Recently I've been experiencing issues with running something like

lessc directory/*.less foo.css

Instead of taking the different LESS's and outputting them into foo.css it would modify the second file in the list. This is not OK with me.

To solve this problem, I made a new less frontend called lessm.

You can check it out at https://github.com/jive/lessm.

The way you'd use it is

lessm foo.less foo2.less ../bar/bazz.less -o output.css
Jessie A. Morris
  • 2,267
  • 21
  • 23
1

If you are looking to compile all LESS files into a folder and subfolder tree in Windows. The following solution is using a batch file in Windows:

File compile-less.bat: @echo
cd ".\pages" for /r %%i in (*.less) do call lessc --clean-css "%%~i" "%%~dpni.min.css" cd ..

EDITED: All the less file in the folder and subfolders will be compiled. Tested in Windows 10 and 8.1

DAme
  • 697
  • 8
  • 21
0

While browsing through all other answers, none of them worked for me. I found a good solution to handle my situation in a combination of answers.

First, you compile all less files into 1 less file. This because it might throw errors (like the bootstrap one).

cat less_directory/* > less_directory/combined.less

Now that you have 1 less file in the less folder, you can compile that one the css without it causing any issues:

lessc less_directory/combined.less > css/style.css

After this, don't forget to throw away the combined.less, otherwise this will mess up the next compile.

rm -f less_directory/combined.less

You can automate this process by making it a batch script

Rene Pot
  • 24,681
  • 7
  • 68
  • 92
0

The way I compiled less files to the corresponding css files in the current folder tree:

find ./ -name '*.less' -type f -exec lessc {} {}.css \; -exec rename -f 's/.less.css/.css/' {}.css \;

For example, if you have main.less somewhere in the folder tree, you will get main.css in the same folder.

But it requires rename command to be installed. To install it with help of Homebrew:

brew install rename
starikovs
  • 3,240
  • 4
  • 28
  • 33
-1

Here is the ideal solution.

Step 1: Create a new .less file that contains an @import statement for each of your existing .less files.

find less_directory/ -name '*.less' -exec echo "@import \"{}\";" \; > combined.less

Step 2: Compile the combined .less file.

lessc combined.less > compiled.css
Jason
  • 185
  • 1
  • 9