web-dev-qa-db-fra.com

Trier la sortie des fichiers / dossiers dans Bash

J'ai une sortie comme ça (alphanumérique):

bash /etc/file
bash /etc/filenew
bash /etc/skel/
bash /etc/skel/file
bash /etc/skel/filenew
bash /etc/skel/new/backups/
bash /etc/skel/new/file
bash /etc/skel/old/backups/
bash /etc/skel/old/file
bash /usr/
bash /usr/bin/
bash /usr/bin/file
bash /usr/sbin/
bash /usr/sbin/file.sbin

Que je dois trier (la sortie elle-même) pour afficher les répertoires en premier, selon:

bash /etc/skel/
bash /etc/skel/new/backups/
bash /etc/skel/new/file
bash /etc/skel/old/backups/
bash /etc/skel/old/file
bash /etc/skel/file
bash /etc/skel/filenew
bash /etc/file
bash /etc/filenew
bash /usr/
bash /usr/bin/
bash /usr/bin/file
bash /usr/sbin/
bash /usr/sbin/file.sbin
3
user504452

Je pense que la commande suivante se rapproche:

sed -r 's:([^/]*/):d\1:g; s:([^/]+)$:f\1:' foo.txt |
  sort |
  sed -r 's:/f:/:; s:d([^/]*/):\1:g'

Qu'est ce que ça fait? La première commande sed ajoute un d au début de chaque répertoire (en recherchant les chaînes qui se terminent par un /) et un f aux fichiers - ceux qui ne se terminent pas par /. Ensuite, nous appliquons sort - et puisque d trie avant f, les répertoires sont d'abord triés. Le second sed annule le premier.

Pour l'exemple d'entrée:

$ sed -r 's:([^/]*/):d\1:g; s:([^/]+)$:f\1:' foo.txt |
 sort |
 sed -r 's:/f:/:; s:d([^/]*/):\1:g'
bash /etc/skel/
bash /etc/skel/new/backups/
bash /etc/skel/new/file
bash /etc/skel/old/backups/
bash /etc/skel/old/file
bash /etc/skel/file
bash /etc/skel/filenew
bash /etc/file
bash /etc/filenew
bash /usr/
bash /usr/bin/
bash /usr/bin/file
bash /usr/sbin/
bash /usr/sbin/file.sbin
4
muru