2

So I'm trying to do a Shell Script (.sh) on my mac, but I'm having a hard time... So for each file I would like to make a copy of it and convert it into another type (.less to .css). I know how to do that already:

 lessc fileToConvert.less destinationOfConvertedFile.css

now my problem is to integrate that into a loop (loop all the files of a folder). I tried that but nothing seems to work:

alias proj="cd /Users/maxwell/Documents/WebStorm"
for /D /r %%G in * DO Echo We found %%G

I tried that as a test, but even that is not working. Any ideas?

aphoria
  • 19,796
  • 7
  • 64
  • 73
  • Which shell are you using? The notation is most peculiar looking to my eyes, and looks more like something from DOS than `bash` or even `tcsh`. Well, maybe it is too late to worry about that; you seem to have an answer. – Jonathan Leffler Jan 16 '14 at 19:38

2 Answers2

7

Use the find command with the -exec switch OR pipe the output of find to xargs.

For example:

find . -name "*.less" -exec sh -c 'lessc "{}" "$(basename "{}" .less).css"' \;

This will recursively find any file with *.less extension, from the current directory, and use the filename as an argument to lessc. The output filename will be the same as the input filename, but with a different extension.

Note that I don't have lessc installed on my system, so I wasn't able to test this exact example, but it should be correct, or very close.

David
  • 6,462
  • 2
  • 25
  • 22
  • 1
    I'm not sure why someone downvoted this answer. "find" is a good answer, and is available on Mac: http://www.maclife.com/article/columns/terminal_101_using_find_command – jeffrey_t_b Jan 16 '14 at 19:18
  • @jeffrey_t_b I was wondering the same thing. Mac uses BSD, so you can run unix shell commands. – David Jan 16 '14 at 19:22
  • Thanks! Can you give a more precise example please, as this does not help me very much. I have very few knowledge on Shell scripts. –  Jan 16 '14 at 19:25
  • @Maxwell Looks like you have a good answer, already, but I went ahead and added an example, in case you're interested. – David Jan 16 '14 at 21:59
4

Here I created a sub folder called test. Inside it are all my *.less files. After I run this it outputs the .css files with the corresponding name. You can easily modify the path to fit your folder structure.

#!/bin/bash
FILES=./test/*.less
for f in $FILES
do
    echo "$f"
    FULL_FILENAME=$f
    FILENAME=${FULL_FILENAME##*/}
    echo ${FILENAME%%.*}
    DIR=${PWD##*/}
    lessc $f ./test/${FILENAME%%.*}.css
done

If you need this in a 1-liner create an alias to this script in your .bash_profile then you can call it from anywhere.

edit: This was helpful in nailing the bash loop http://www.cyberciti.biz/faq/bash-loop-over-file/

Cheers

inburst
  • 56
  • 3
  • 3
    +1. Comment: I'd make sure that I quoted `$f` and `$FILENAME` when using them; I would not bother with `FULL_FILENAME` (reference `"$f"` instead) and since `DIR` is unused, I'd remove that too (or I'd fix the `lessc` command line to use `$DIR`). The double quotes protect you if the file names contain spaces, etc. Unless I had a use for `FILES` elsewhere in the script, I'd simply write `for f in ./test/*.less`, or for a general purpose script, `for f in "$@"`. Hmmm; and the `${FILENAME%%.*}` is too enthusiastic; you should probably use `${FILENAME%.less}`. Try `x=a.b.c.d; echo ${x%%.*}`. – Jonathan Leffler Jan 16 '14 at 19:41
  • `FILES=./test/*.less` isn't actually making `FILES` a list of files, it's just storing the glob expression itself with that name. `files=( ./test/*.less ); for f in "${files[@]}"` would actually be storing the files in an array named `files`. – Charles Duffy Apr 12 '17 at 00:01
  • BTW, all-caps variable names are reserved by POSIX convention for variables with meaning to the OS or system -- see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, fourth paragraph, keeping in mind that environment variables and and regular shell variables share a namespace (setting the latter will overwrite the former if any exist with the same name). – Charles Duffy Apr 12 '17 at 00:02