На этот вопрос уже есть ответ:
Как мне отобразить все папки, у которых нет подкаталогов, с помощью терминала?
Попробуйте это:
find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
Для сейфа для всех возможных имен каталогов мы используем nul-разделенные списки для каждого шага конвейера.
find . -type d -print0
Это получает список всех подкаталогов текущего каталога.
sort -z
Это сортирует каталоги который как эффект помещения подкаталогов после их родительских каталогов.
gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
Это помещает список каталогов в ассоциативном массиве. Для каждого добавленного каталога это проверяет, чтобы видеть, находится ли родитель каталогов в массиве. Если это, это удаляет его из массива. Давайте посмотрим на этот шаг за один раз:
a[$0]
Это добавляет каталог, названный в текущей записи как ключ в массиве a
. (Мы не присваиваем значение ему, потому что нам не нужно значение.)
sub(/[/][^/]*$/, "")
Это удаляет последний подкаталог из $0
так, чтобы $0
теперь обращается к родительскому каталогу.
if ($0 in a) delete a[$0]
Если родительский каталог является ключом a
, затем мы удаляем его.
END{for (d in a) print d}
Это распечатывает каждый каталог, для которого мы не нашли подкаталогов. (Из-за пути работают массивы awk, вывод без определенного порядка.)
RS='\0'
Это говорит awk ожидать nul-разделенный вход. Другими словами, на входе, awk использует nul символ в качестве разделителя записей.
Давайте создадим некоторые каталоги и затем проверим, что вывод перечисляет только те каталоги, которые не имеют никаких подкаталогов:
$ mkdir -p a/b/c/x1 a/b/c/x2 a/b/x3 a/x4
$ find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
./a/x4
./a/b/x3
./a/b/c/x1
./a/b/c/x2
find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a) {sub(/^.*[/]/,"",d); print d}}' RS='\0'
Для иллюстрирования давайте выполним это против тех же каталогов как выше:
$ find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a) {sub(/^.*[/]/,"",d); print d}}' RS='\0'
x5
x4
x3
x1
x2
Вы могли сделать find-within-a-find, например,
find . -type d -exec bash -c '
[[ -z $(find "$1" -mindepth 1 -type d -print -quit) ]] && printf "%s\n" "$1"
' bash {} \;
, Если Вы не хотите ведущие компоненты контура, затем
find . -type d -exec bash -c '
[[ -z $(find "$1" -mindepth 1 -type d -print -quit) ]] && printf "%s\n" "${1##*/}"
' bash {} \;
<час> , я не могу сдержать чувство, что должен быть "умный" способ сделать это с помощью -depth