How can I list only folders with no sub folders in given path?

Problem:I have given dir structure

├── kat11
│   ├── kat21
│   │   └── Dokument\ bez\ nazwy
│   └── kat22
│       ├── kat31
│       │   └── Dokument\ bez\ nazwy
│       └── kat32
│           └── Dokument\ bez\ nazwy
├── kat12
│   └── kat21
│       └── Dokument\ bez\ nazwy
├── kat13
│   └── Dokument\ bez\ nazwy
└── kat14
    └── Kat21
        └── Kat32
            └── Dokument\ bez\ nazwy

I want to list only all the child folders with full path.

eg

1. /kat14/kat21/kat32/Dokument\ bez\ nazwy
2. /kat11/kat22/kat31/Dokument\ bez\ nazwy
3. /kat11/kat22/kat32/Dokument\ bez\ nazwy
4. /kat12/kat21/Dokument\ bez\ nazwy

Solution 1:

In a small python script:

 #!/usr/bin/env python3
import os
import sys

src = sys.argv[1]
for root, dirs, files in os.walk(src):
    for dr in dirs:
        directory = root+"/"+dr
        if len([sub for sub in os.listdir(directory) \
                if os.path.isdir(directory+"/"+sub)]) == 0:
            print(directory)

To use it

  • Copy it into an empty file, save it as count_empty.py
  • Run it with the targeted directory as an argument:

    python3 /path/to/count_empty.py '<source_directory>'
    

How it works

  • python's os.walk() walks through directories and sub- directories
  • The line

    if len([sub for sub in os.listdir(directory) if os.path.isdir(directory+"/"+sub)]) == 0:
    

    subsequently counts the number of subdirectories on each of them. If it is zero (no subdirectories), the directory and its path is printed.

Test on a simple package folder on my desktop:

$ '/home/jacob/Bureaublad/pscript_5.py' '/home/jacob/Bureaublad/0.5.3' 
/home/jacob/Bureaublad/0.5.3/nonotifs-0.5.3/manpages
/home/jacob/Bureaublad/0.5.3/nonotifs-0.5.3/miscellaneous
/home/jacob/Bureaublad/0.5.3/nonotifs-0.5.3/icon
/home/jacob/Bureaublad/0.5.3/nonotifs-0.5.3/code
/home/jacob/Bureaublad/0.5.3/nonotifs-0.5.3/debian/source

Solution 2:

A simple find should be enough:

find /path/to/dir -type d -empty

For example:

$ tree foo
foo
├── 1
│   ├── 1
│   ├── 2
│   └── 3
├── 2
│   ├── 1
│   ├── 2
│   └── 3
└── 3
    ├── 1
    ├── 2
    └── 3

12 directories, 0 files
$ find foo -type d -empty
foo/2/2
foo/2/3
foo/2/1
foo/3/2
foo/3/3
foo/3/1
foo/1/2
foo/1/3
foo/1/1
$ touch foo/1/1/a foo/2/1/a foo/3/1/a 
$ find foo -type d -empty            
foo/2/2
foo/2/3
foo/3/2
foo/3/3
foo/1/2
foo/1/3

If these directories can contain files, then this would be better, but expensive:

find foo -type d -exec sh -c 'find "$0" -mindepth 1 -type d -printf z | grep -q z || printf "%s\n" "$0"' {} \;

This Stack Overflow post has a rather neat solution:

find /path/to/dir -type d -links 2

Since a directory without subdirectories only has two hard links, one two its parent and one to itself.

The question, phrased differently, has been asked before on Stack Overflow, Super User and Unix & Linux:

  • Use GNU find to show only the leaf directories
  • List all leaf subdirectories in linux
  • Using “find” to list only directories with no more childs
  • find all end subdirectories in a tree