Wie füge ich die Farben des ls-Befehls mit der Ausgabe von find oder du zusammen?

Wie füge ich die Farben des ls-Befehls mit der Ausgabe von find oder du zusammen?

Ich habe einen einfachen Alias, um die Größe von Dateien und Ordnern in cwd aufzulisten.

(in diesem Fall einschließlich Dotfiles, Nullgrößen werden ignoriert)

du -sh .[!.]* * | sort -hr | grep -v '^0'

was auch mit find erreicht werden kann:

find .[!.]* * -maxdepth 0 -exec du -sh {} \; | sort -hr | grep -v '^0'

Beispielausgabe:

// .ssh & .byobu are folders - .zsh* are files
// currently not able to distinguish them by type

... 
32K     .zshrc
25K     .ssh
20K     .zcompdump
19K     .byobu
...

Wie kann ich die Dateien/Verzeichnisse in der Ausgabe passend zu den LS-Farben einfärben?( LS_COLORS )

Antwort1

Dieses zshSkript analysiert $LS_COLORS. Es muss nur statfür jede Datei aufgerufen werden und ist daher viel schneller als die Lösung unten, die lsfür jede Datei aufruft. Und es verarbeitet Dateien mit Leerzeichen korrekt. ( \noder \tsind immer nochnichtin Dateinamen erlaubt)

Die Implementierung ist jedoch nicht vollständig. Ich habe nur Farben für verschiedene Dateitypen aufgenommen, die am ersten Zeichen des Dateimodus-Strings (z. B. lrwxrwxrwxfür einen symbolischen Link) oder an der Dateierweiterung identifiziert werden können. Das bedeutet, dass allgemein schreibbare Berechtigungen, Suid- oder Sticky-Bits nicht speziell eingefärbt werden. Diese ebenfalls einzubinden sollte unkompliziert sein.

sourceFolgendes und verwenden Sie die neue Shell-Funktion ducfür eine farbige duAusgabe:

zmodload -F zsh/stat b:zstat

function duc() {

  emulate zsh 
  setopt no_nomatch interactivecomments           # no_nomatch is necessary, to prevent error in "do .* *" if there are no dotfiles

  typeset -a aline
  typeset -A lscols
  local dircols acolor

  for i (${(s.:.)LS_COLORS}) {                    # split $LS_COLORS at ":"
    aline=(${(s:=:)i})                            # split every entry at "="
    lscols+=(${${aline[1]}/*.} ${aline[2]})       # load every entry into the associative array $lscols
  }

  duout=$(du -sh .* * 2> /dev/null | grep -v '^0' | sort -hr)
  for i (${(f)duout}) {                           # split output of "du" at newlines
    aline=(${(ps:\t:)i})                          # split every entry at \t
    zstat -s +mode -A atype ${aline[2]}           # determine mode (e.g. "drwx------") of file ${aline[2]}
    case ${${atype[1]}[1]} in                     # ${${atype[1]}[1]} is the first character of the file mode
      b)   acolor=$lscols[bd] ;;
      c|C) acolor=$lscols[cd] ;;
      d)   acolor=$lscols[di] ;;
      l)   acolor=$lscols[ln] ;;
      p)   acolor=$lscols[pi] ;;
      s)   acolor=$lscols[so] ;;
      -)   acolor=${lscols[${${aline[2]}:e}]};      # ${${aline[2]}:e} is the current file extention
           [[ -z $acolor ]] && acolor=$lscols[fi]   # unrecognized extention
           [[ -z $acolor ]] && acolor=00            # sometimes "fi" isn't set in $LS_COLORS, so fall back to normal color
           ;;
      *)   acolor=00 ;;
    esac
    print -n -- "${aline[1]}\t"        # print size (taken from du output)
    print -n "\\e[4${acolor}m"         # activate color
    print -n ${aline[2]}               # print file name
    print "\\e[0m"                     # deactivate color
  }
}

Dies ist mein altes Skript, auch für zsh. Es ist wahrscheinlich unnötig komplex und wirklich langsam, da für jede Datei ein einzelner lsBefehl ausgegeben wird:

du_colored() {
  typeset -a duout
  duout=($(du -sh .* * | sort -hr | grep -v '^0'))
  for i ({1..$#duout..2}) {
    print -n "${duout[$i]}\t"
    ls -d --color ${duout[$(($i+1))]}
  }
}
  • das .*in zshwirdnichtmatch .oder .., aber Dateien wie ..foowhich werden mit.[!.]*
  • typeset -adeklariert ein Array
  • die for-Schleifen durchlaufen das Array und $inehmen Werte ab 1 in 2er-Schritten an

Warnung: Dies wird schlecht funktionieren, wenn es Dateien mitRohlinge... mir fällt im Moment keine bessere Idee ein.

Antwort2

Das ist, was ich mir für Bash ausgedacht habe – verwendet PV, um den Ausgabefortschritt anzuzeigen

folder_size (){
  # read ls --color output into ls_colored_array 
  # thereby remove symlinks (@) and remove (/ and *) from folders and files

  ls -AF --color | grep -v @ | sed s'/[/\,*]$//'| xargs -n1 -L1 | read -d '\n' -r -a ls_colored_array

  # - loop over the array and issue du -sh for every element
  # - exchange du's ouput with ls's 
  # - run loop through pv with line option and
  #    size set to array-length showing progress
  # - finally sort the output using sort

  for i in "${ls_colored_array[@]}"; do
    echo -n "${i}" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | xargs -n1 -0 du -sh | awk -v i="$i" '{ printf "%-10s ", $1; $1=""; print i }'
  done | pv -pls"${#ls_colored_array[@]}" | sort -hr
}

Das Skript kann jetzt in eine Einzeilerzeile umgewandelt werden … aber ich werde die Funktion verbessern, indem ich Flags für z. B. die 10 größten Dateien/Ordner oder nur Ordner hinzufüge.

Antwort3

Das funktioniert bei mir:

#!/usr/bin/env bash

paste <(du --apparent-size --all --human-readable --max-depth=1 2>/dev/null |
    sed 's/\s.*//') \
    <(ls --color=always -1 --almost-all -U) | sort --human-numeric-sort

Der Hauptbefehl hier ist paste, er verbindet die Ausgaben von lsund duhorizontal.

dugibt jede Zeile ungefähr so ​​aus:

147291    ./.config

sed 's/\s.*//löscht alles nach und einschließlich dem ersten Leerzeichen, d. h. ./.configda wir an den nicht farbigen Formen der Namen der aufgelisteten Einträge nicht interessiert sind. Der Trick dabei ist, lsden Inhalt des Verzeichnisses auf die gleiche Weise auszugeben wie, dudamit wir jeden Eintrag mühelos mit der entsprechenden Größe verbinden können. Das können wir mithilfe von -1(das die Einträge vertikal statt horizontal auflistet), -U(das die Einträge in Verzeichnisreihenfolge auflistet, genau wie du, statt alphabetisch) und (das auch versteckte Verzeichnisse/Dateien auflistet, aber und im Gegensatz zu --almost-allauslässt ) und natürlich . Für wird benötigt, damit sowohl Dateien (einschließlich versteckter) als auch Verzeichnisse statt nur Verzeichnisse verarbeitet werden und keine Unterverzeichnisse mehr bearbeitet (genau wie 's )....--all--color=alwaysdu--all--max-depth=1dufind-maxdepth 1

Um die Frage zu beantworten, ist also nur Folgendes erforderlich:

paste <(du --all --max-depth=1 | sed 's/\s.*//') \
    <(ls --color=always -1 --almost-all -U)

Was die anderen optionalen Argumente betrifft:

  • --apparent-sizedruckt duscheinbare Größen, statt Festplattennutzung (meine Präferenz)
  • --human-readabledruckt für Menschen lesbare Größen
  • 2>/dev/nullfiltert alle permission deniedFehler heraus, wenn Sie versucht haben, duin einem eingeschränkten Verzeichnis zu laufen, zB/var
  • sort --human-numeric-sortsortiert die Größen in absteigender Reihenfolge, --human-numeric-sortwird benötigt, wenn --human-readableandu

Antwort4

Durch die Kombination einiger der obigen Antworten mit oh-my-zshell auf einem Mac erhielt ich Größenangaben, farbige Verzeichnisnamen und Dateinamen im Klartext, die so sortiert waren, dass die 10 größten Dateien/Verzeichnisse ausgegeben wurden:

paste <(du -cks *) <(ls --color=always -1) | sort -nr | head | awk '{print $1 "  " $3}'

Erklärung:
duzur Datenträgernutzung -c:grand total -k: 1Kb blocks -s: entryfür jede Datei;
lszum Erfassen der Farbe für Verzeichnisse;
pastezum Kombinieren der beiden obigen Ausgaben;
sort -nr: numerische Rückwärtssortierung;
head: gibt die größten Dateien/Verzeichnisse aus;
awk: um nur die erste Spalte (Größe) und die 3. Spalte (Datei/farbiger Verzeichnisname) auszugeben

verwandte Informationen