Wie kann ich auf einem Mac den Inhalt eines nicht aktuellen Verzeichnisses auflisten, ohne Sicherungsdateien (die mit ~ enden) anzuzeigen, vorzugsweise mit dem BSD-Befehl ls?

Wie kann ich auf einem Mac den Inhalt eines nicht aktuellen Verzeichnisses auflisten, ohne Sicherungsdateien (die mit ~ enden) anzuzeigen, vorzugsweise mit dem BSD-Befehl ls?

Mein System:

  • Betriebssystem: MacOS / Mac OS X (Mojave 10.14.5)
  • Betriebssystemkern: Darwin (18.6.0)
  • Kernel: Darwin Kernel / XNU (18.6.0 / xnu-4903.261.4~2/RELEASE_X86_64)
  • ls: Version unbekannt, man lsgibt aber eine Seite aus dem BSD General Commands Manual
  • Muscheln:
    • Bash: GNU Bash, Version 5.0.7(1)-Release (x86_64-apple-darwin18.5.0)
    • Zsh: zsh 5.7.1 (x86_64-apple-darwin18.2.0)

Unter MacOS möchte ich in einer Terminal-CLI mit einer Shell wie Bash oder Zsh den Befehl (BSD) (oder vielleicht ein ähnlich gebräuchliches und nützliches Tool) verwenden, um den Inhalt eines anderen Verzeichnisses als des aktuellen Arbeitsverzeichnisses aufzulisten, wobei alle Dateien außer denen angezeigt werden, lsdie mit einer Tilde ( ) enden .~

Abgesehen von der letzten Bedingung lswird diese Aufgabe auf natürliche Weise erfüllt, wenn das nicht aktuelle Verzeichnis als Argument für verwendet wird ls: ls argwobei argein absoluter oder relativer Pfad zum nicht aktuellen Verzeichnis ist (z. B. /absolute/path/to/directory, ~/path/from/home/to/directory, oder path/from/current/dir/to/directory).

Ich weiß, wie man nicht gesicherte Inhalte im aktuellen Verzeichnis auflistet, indem ich die Dateinamenerweiterung (auch „Globbing“ genannt) und die -dOption (Verzeichnisse und nicht deren Inhalte aufzulisten) verwende, etwa so: ls -d *[^~](oder ls -d *[!~]). Ich möchte die gleichen Ergebnisse, aber für ein nicht aktuelles Verzeichnis.

Ich kann fast das erreichen, was ich will, indem ich verwende ls -d arg/*[^~], wobei argdasselbe ist wie oben beschrieben, aber die Ergebnisse zeigen den Pfad zu jedem Inhaltselement (also zu jeder Datei und jedem Verzeichnis im betreffenden Verzeichnis). Ich möchte lsjedes Element ohne den Pfad dazu anzeigen, so wie es mit gemacht wird ls arg.

Unter Linux lskann ich mit dem GNU-Befehl genau das erreichen, was ich will, indem ich die -BOption verwende, Sicherungsdateien nicht aufzulisten: ls -B arg. Obwohl das mein Wunsch ist, würde ich dies gerne mit nativen Tools von MacOS erreichen, vorzugsweise BSD ls.

grepHinweis: Ich möchte (zB, ls arg | grep '.*[^~]$') nicht verwenden , da grepdies die Formatierung und Farbgebung der Ausgabe ändert.

Fragenzusammenfassung: Wie kann ich auf einem Mac den Inhalt eines nicht aktuellen Verzeichnisses, jedoch nicht die Sicherungsdateien auflisten, vorzugsweise mit ls?

Antwort1

Sie könnten lsin einer Subshell ausführen:

(cd arg; ls -d *[^~])

Antwort2

Verwenden Sie bashund seine GLOBIGNOREShell-Variable zusammen mit dem von macOS basename:

$ mkdir dir
$ touch dir/file{1,2}{,~}
$ ls -R
dir

./dir:
file1   file1~  file2   file2~
$ GLOBIGNORE=*~
$ ls -d dir/*
dir/file1       dir/file2
$ basename -a dir/*
file1
file2

GLOBIGNOREWenn Sie eine Liste mit durch -getrennte Muster festlegen :, werden diese Muster bei der Dateinamenvervollständigung ignoriert.

Das basenameDienstprogramm in macOS akzeptiert mehr als einen Pfadnamen, wenn Sie die entsprechende -aOption verwenden, und gibt eine Liste zurück, die nur aus den Dateinamenteilen dieser Pfadnamen besteht.

Anstatt zu verwenden GLOBIGNORE(was eine allgemeinere Möglichkeit bietet, bestimmte Mustererweiterungen für Dateinamen zu ignorieren), können Sie natürlich Ihr Muster verwenden *[!~](beachten Sie, dass !eine Zeichenklasse in der Shell negiert wird, während ^eine Zeichenklasse in regulären Ausdrücken negiert wird):

unset GLOBIGNORE
basename -a dir/*[!~]

... oder Sie installieren einfach GNU Coreutils von Homebrew und verwenden es gls -Bwie gewohnt auf Linux-Systemen.

Antwort3

Die kurze Antwort besteht darin, eine Subshell zu verwenden, um den Befehl im nicht aktuellen Verzeichnis auszuführen:

(cd arg; ls -d *[^~])

Um jedoch eine allgemeine Funktion zu erstellen, die sowohl für das aktuelle als auch für alle anderen Verzeichnisse funktioniert, können wir Folgendes zu .bashrc(oder zu bashrc_aliases_lsBSD, Quelle .bashrc: ) hinzufügen:

alias ls='/bin/ls'
alias   l=''
unalias l
function l () { ( if [[ -n "$@" ]]; then cd "$@"; fi ; /bin/ls -d *[^~] ) }

Wenn wir uns der oben genannten Präferenz für die Verwendung von BSD widersetzen, können wir GNU lsproblemlos verwenden, indem wir die GNU-Kerndienstprogramme installieren (z. B. über brew install coreutils) und die gewünschten Aliase (anstatt den obigen Code zu verwenden) in .bashrc(oder in bashrc_aliases_lsGNU, bezogen von .bashrc) erstellen:

alias ls='/usr/local/bin/gls'
alias l='/usr/local/bin/gls -B'

Meine eigene aktuelle Lösung besteht darin, beide Konstruktionen zu verwenden und bei Bedarf zwischen ihnen zu wechseln. Dazu verwende ich eine Variable, die ich aufrufe, LS_TYPEund eine Funktion, die ich aufrufe ls-switch(definiert in bashrc_aliases, bezogen von .bashrc), die eine von zwei Konfigurationsdateien als Quelle verwendet, die diese beiden Konstruktionen enthalten:

function ls-switch () {
    if [[ $LS_TYPE = "GNU" ]] ; then
        LS_TYPE="BSD"
        source ~/.config/bash/bashrc_aliases_lsBSD
    elif [[ $LS_TYPE = "BSD" ]] ; then
        LS_TYPE="GNU"
        source ~/.config/bash/bashrc_aliases_lsGNU
    fi
}

Bei dieser Anordnung werden die Standardverhaltensweisen von lsund mit der ersten Definition von und der Auswahl der als Quelle verwendeten Konfigurationsdatei lfestgelegt , zum Beispiel:.bashrcLS_TYPE

LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD

verwandte Informationen