Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sort files by depth (bash)

Tags:

bash

sorting

Is there a way in bash to sort my files from a directory down in depth order, for example first print the files in the present directory, then the files in the sub directory or sub directories and so forth, always in perspective to their depth.

like image 636
sergio Avatar asked Jul 28 '12 19:07

sergio


People also ask

How do I sort files in bash?

Bash Sort Files Alphabetically By default, the ls command lists files in ascending order. To reverse the sorting order, pass the -r flag to the ls -l command, like this: ls -lr . Passing the -r flag to the ls -l command applies to other examples in this tutorial.

How do I sort files in Shell?

the -r flag is an option of the sort command which sorts the input file in reverse order i.e. descending order by default. Example: The input file is the same as mentioned above. 3. -n Option: To sort a file numerically used –n option.

How do I list files alphabetically in Linux?

The easiest way to list files by name is simply to list them using the ls command. Listing files by name (alphanumeric order) is, after all, the default. You can choose the ls (no details) or ls -l (lots of details) to determine your view.

How do I sort files in Ubuntu?

To sort files in a different order, click the view options button in the toolbar and choose By Name, By Size, By Type, By Modification Date, or By Access Date. As an example, if you select By Name, the files will be sorted by their names, in alphabetical order.


2 Answers

Use find's "-printf" feature in combination with sort. See for yourself:

find . -printf "%d %p\n"|sort -n

It generates a depth-sorted list (displaying the depth in the first column, file path in the second). This prints in my current dir:

0 .
1 ./bin
1 ./log
1 ./templates
2 ./bin/cc_env
3 ./files/test/mail.txt

If you want to strip the first column, we can use perl:

find . -printf "%d %p\n"|sort -n|perl -pe 's/^\d+\s//;'

and off you go. The perl filter will remove all leading numbers. In case you want to omit directories themselves, use the '-type f' parameter:

find . -type f -printf "%d %p\n"|sort -n|perl -pe 's/^\d+\s//;'

Hint: Study the find manpage for more printf %d-like tricks.

like image 79
muenalan Avatar answered Sep 27 '22 21:09

muenalan


The simplest solution:

$ echo * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*
a a/b a/b/c a/b/c/d1 a/b/c/d2 a/b/c/d1/e a/b/c/d2/e a/b/c/d1/e/f a/b/c/d2/e/f

Or, in column:

$ echo * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/* |tr ' ' '\n'
a
a/b
a/b/c
a/b/c/d1
a/b/c/d2
a/b/c/d1/e
a/b/c/d2/e
a/b/c/d1/e/f
a/b/c/d2/e/f

The depth of the tree is hardcoded in the example, but you can write a small script and make it more flexible:

A="*"
while true
do
  B=$(echo $A)
  [ "$B" = "$A" ] && break
  echo $B
  A="$A/*"
done | tr ' ' '\n'

Example of usage:

$ A="*"; while true; do B=$(echo $A); [ "$B" = "$A" ] && break; echo $B; A="$A/*"; done | tr ' ' '\n'
a
a/b
a/b/c
a/b/c/d1
a/b/c/d2
a/b/c/d1/e
a/b/c/d2/e
a/b/c/d1/e/f
a/b/c/d2/e/f

Examples are provided for the tree:

$ mkdir -p a/b/c/d{1,2}/e/f
$ tree .
.
└── a
    └── b
        └── c
            ├── d1
            │   └── e
            │       └── f
            └── d2
                └── e
                    └── f

9 directories, 0 files

Find/depth solutions will obviously not work because find will shows subtrees one after another. The -depth key says in which direction subtree must be shown. But that doesn't mean, of course, that the output will be sorted by depth.

$ find .
.
./a
./a/b
./a/b/c
./a/b/c/d2
./a/b/c/d2/e
./a/b/c/d2/e/f
./a/b/c/d1
./a/b/c/d1/e
./a/b/c/d1/e/f

$ find . -depth
./a/b/c/d2/e/f
./a/b/c/d2/e
./a/b/c/d2
./a/b/c/d1/e/f
./a/b/c/d1/e
./a/b/c/d1
./a/b/c
./a/b
./a
.

As you can see the answer is incorrect in both cases (with and without -find).

like image 34
Igor Chubin Avatar answered Sep 27 '22 23:09

Igor Chubin