Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terminal find, directories last instead of first

I have a makefile that concatenates JavaScript files together and then runs the file through uglify-js to create a .min.js version.

I'm currently using this command to find and concat my files

find src/js -type f -name "*.js" -exec cat {} >> ${jsbuild}$@ \;

But it lists files in directories first, this makes heaps of sense but I'd like it to list the .js files in the src/js files above the directories to avoid getting my undefined JS error.

Is there anyway to do this or? I've had a google around and seen the sort command and the -s flag for find but it's a bit above my understanding at this point!

[EDIT]

The final solution is slightly different to the accepted answer but it is marked as accepted as it brought me to the answer. Here is the command I used

cat `find src/js -type f -name "*.js" -print0 | xargs -0 stat -f "%z  %N" | sort -n | sed -e "s|[0-9]*\ \ ||"` > public/js/myCleverScript.js
like image 848
Dave Mackintosh Avatar asked Dec 01 '13 18:12

Dave Mackintosh


3 Answers

Possible solution:

  1. use find for getting filenames and directory depth, i.e find ... -printf "%d\t%p\n"
  2. sort list by directory depth with sort -n
  3. remove directory depth from output to use filenames only

test:

without sorting:

$ find folder1/ -depth -type f -printf "%d\t%p\n"
2   folder1/f2/f3
1   folder1/file0

with sorting:

$ find folder1/ -type f -printf "%d\t%p\n" | sort -n | sed -e "s|[0-9]*\t||"
folder1/file0
folder1/f2/f3

the command you need looks like

cat $(find src/js -type f -name "*.js" -printf "%d\t%p\n" | sort -n | sed -e "s|[0-9]*\t||")>min.js
like image 131
Sergey Fedorov Avatar answered Oct 21 '22 16:10

Sergey Fedorov


Mmmmm...

find src/js -type f

shouldn't find ANY directories at all, and doubly so as your directory names will probably not end in ".js". The brackets around your "-name" parameter are superfluous too, try removing them

find src/js -type f -name "*.js" -exec cat {} >> ${jsbuild}$@ \;
like image 25
Mark Setchell Avatar answered Oct 21 '22 17:10

Mark Setchell


find could get the first directory level already expanded on commandline, which enforces the order of directory tree traversal. This solves the problem just for the top directory (unlike the already accepted solution by Sergey Fedorov), but this should answer your question too and more options are always welcome.

Using GNU coreutils ls, you can sort directories before regular files with --group-directories-first option. From reading the Mac OS X ls manpage it seems that directories are grouped always in OS X, you should just drop the option.

ls -A --group-directories-first -r | tac | xargs -I'%' find '%' -type f -name '*.js' -exec cat '{}' + > ${jsbuild}$@

If you do not have the tac command, you could easily implement it using sed. It reverses the order of lines. See info sed tac of GNU sed.

tac(){
    sed -n '1!G;$p;h'
}
like image 1
Palec Avatar answered Oct 21 '22 17:10

Palec