ls -l --group-directory-first (agit également sur les liens symboliques)

9

lsL'option --group-directories-firstfait apparaître les répertoires en haut, ce qui rend la sortie lsagréable et propre:

ls -l --group-directories-first

Cependant, il n'agit pas symlinks, qui sont en fait symlinksà des répertoires. Il est possible d'utiliser

ls -l -L --group-directories-first

qui listera les deux types de répertoires en haut, mais ne fera pas de distinction entre le répertoire approprié et le répertoire avec lien symbolique, ce qui est encore une fois déroutant.

Peut-il lsafficher des répertoires liés par des liens symboliques sur le dessus, tout en les gardant distincts des répertoires classiques?

EDIT: J'utilise bash.

Martin Vegter
la source
C'est un comportement idiosyncratique de la part de ls. Selon l' stat()appel système, un lien symbolique vers un répertoire est toujours un répertoire ( S_ISDIR(st_mode)renvoie true). Evite évidemment lsles liens symboliques avant de vérifier cela.
goldilocks
2
@goldilocks, non, lsne lstat()(et readlinkpour les liens symboliques) sauf si vous utilisez l' -Loption de (auquel cas il utilise stat())
Stéphane Chazelas
@StephaneChazelas: Hmm, vivez et apprenez. J'avais pensé que cela était S_ISLNK(st_mode)également vrai via stat(), mais ce n'est pas le cas - il le fait uniquement via lstat(). De plus, ISLNK ne renvoie pas true via stat même si le lien est un lien vers un lien. Ce qui ISLNKpourrait ne jamais revenir vrai via stat, bien que ce soit un peu indéterminé ...
goldilocks
@goldilocks, statvous donne les propriétés du fichier à la fin du ou des liens symboliques. Si cela n'existe pas ou n'est pas accessible, le statretourne un ENOENT, donc ce qui est retourné par statne sera jamais un lien symbolique. stat()ne vous dira jamais rien à propos des liens symboliques, tout comme openn'ouvrira jamais le lien symbolique, ou chmod()ne changera pas les autorisations d'un lien symbolique ... etc.
Stéphane Chazelas

Réponses:

5

Non, mais si vous utilisez zsh, vous pouvez faire:

mll() {
  (($#)) || set -- *(N-/) *(N^-/)
  (($#)) && ls -ldU -- $@
}

Vous pouvez également définir un ordre de tri global comme:

dir1st() { [[ -d $REPLY ]] && REPLY=1-$REPLY || REPLY=2-$REPLY;}

et l'utiliser comme:

ls -ldU -- *(o+dir1st)

De cette façon, vous pouvez l'utiliser pour d'autres commandes que lsou lsavec différentes options, ou pour différents modèles comme:

ls -ldU -- .*(o+dir1st) # to list the hidden files and dirs

ou:

ls -ldU -- ^*[[:lower:]]*(o+dir1st) # to list the all-uppercase files and dirs

Si vous devez utiliser bash, l'équivalent serait comme:

mll() (
  if (($# == 0)); then
    dirs=() others=()
    shopt -s nullglob
    for f in *; do
      if [[ -d $f ]]; then
        dirs+=("$f")
      else
        others+=("$f")
      fi
    done
    set -- "${dirs[@]}" "${others[@]}"
  fi
  (($#)) && exec ls -ldU -- "$@"
)

bashn'a pas de qualificatifs de globalisation ou aucun moyen d'affecter l'ordre de tri des globes, ni aucun moyen de transformer nullglob sur une base par glob, ou d'avoir un contexte local pour les options (autre que le démarrage d'un sous-shell, d'où la ()place de {}ci - dessus) AFAIK .

Stéphane Chazelas
la source
1
Existe-t-il une astuce similaire pour bash?
Martin Vegter