Программы
Как получить дерево директорий на Bash одним однострочником

Как получить дерево директорий на Bash одним однострочником

Велик и могуч язык Bash! И много в нём возможностей для написания маленьких, но гордых однострочных команд, что могут, например, вывести дерево директорий на Bash одним однострочником.

Сам рецепт на Bash:

ls -R | grep ':$' | sed -e 's/:$//;s/[^─][^\/]*\//──/g;s/^/ /;s/─/├/'

Выводит он для директории мини-мануалов примерно следующее:

 .
 ├─pages
 ├───android
 ├───common
 ├───linux
 ├───osx
 ├───sunos
 ├───windows
 ├─scripts

Замечательно же! Теперь давайте разберёмся, как он это делает. Начнём с ls -R:

$ ls -R
.:
pages  readme.ru  scripts

./pages:
android  common  linux  osx  sunos  windows

./pages/android:
am.md          cmd_ru.md       getprop.md     logcat_ru.md    wm.md
...

./pages/common:
 2to3.md                       jdupes.md
...

./pages/linux:
a2disconf.md             hlint.md                  pvcreate.md
...

./pages/osx:
afinfo.md         eval.md             n.md               spotify.md
...

./pages/sunos:
devfsadm.md     prctl_ru.md    runsvdir.md   svccfg.md     truss.md
...

./pages/windows:
assoc.md            cmd.md          mount.md        rmdir.md
...
./scripts:
untr.py

У утилиты ls есть ключ -R для рекурсивного обхода вложенных папок. Благодаря ему нам на вывод выдаётся столько информации. Теперь самое время эту информацию обработать. А точнее - оставить вывод только папок. Для этого подойдёт grep Тут, к примеру, мы выводим только то, что оканчикается на ":" - то есть директории:

$ ls -R | grep ':$'
.:
./pages:
./pages/android:
./pages/common:
./pages/linux:
./pages/osx:
./pages/sunos:
./pages/windows:
./scripts:

В принципе, это уже то, что мы хотели - вывод директорий, вложенных в данную. Но теперь хочется сделать это красиво. Теперь нам нужен sed!

$ ls -R | grep ':$' | sed -e 's/:$//;'
.
./pages
./pages/android
./pages/common
./pages/linux
./pages/osx
./pages/sunos
./pages/windows
./scripts

Убрали финальное ":", если оно в конце строки и

ls -R | grep ':$' | sed -e 's/:$//;s/[^─][^\/]*\//──/g;s/^/ /;'
 .
 ──pages
 ────android
 ────common
 ────linux
 ────osx
 ────sunos
 ────windows
 ──scripts

заменили символы, которые не и не следующий за ним / - что обычно смена директории "внутрь", на уровень вложенности, а именно - на ──. Далее буквально правило - s/^/ / - "Смотри, если видишь начало, поставь пробел".

И финальный этап:

$ ls -R | grep ':$' | sed -e 's/:$//;s/[^─][^\/]*\//──/g;s/^/ /;s/─/├/'
 .
 ├─pages
 ├───android
 ├───common
 ├───linux
 ├───osx
 ├───sunos
 ├───windows
 ├─scripts

В часности, последняя часть: s/─/├/ - это также sed, как вы поняли, но суть в выставлении для первых найденныйх - чисто для того, чтобы вам было удобно смотреть.

Вот такой простой этот нескучный однострочник!