GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Fehlende Pfade aus dem Bash-Array von Pfaden extrahieren

Sie haben bereits den unmittelbaren Grund entdeckt, warum Ihr Code nicht das getan hat, was Sie erwartet haben:Fehler von ls werden an stderr gemeldet (wie von POSIX vorgeschlagen), was nicht als Eingabe von der Pipe erfasst wird. Sie haben also eine Mischung aus normaler Ausgabe (die unverändert durch Ihren sed gelaufen ist Anweisungen) und stderr (was sie umgangen hat). Ich weiß nicht, warum Ihr ls Ausgabe zwischen Aufrufen geändert; Das Umleiten von stdout nach /dev/null sollte bewirken, dass alle "normalen" (vorhandenen Pfade) aus der Ausgabe entfernt werden. Die Lösung dafür ist nicht aber stderr in stdout zu schieben.

Nachbearbeitung der Ausgabe von ls ist eine gefährliche Idee, wenn Sie ein zuverlässiges Skript wollen. Ein guter Artikel zu diesem Thema ist "Why you should't parse the output of ls(1)", verfügbar auf der Wooledge.org-Site. Eine ausführliche Frage/Antwort auf der Unix- und Linux-Site geht auf einige der Probleme ein:Warum nicht parse ls (und was ist stattdessen zu tun)?. Das Ergebnis ist, dass UNIX-Dateinamen fast jedes Zeichen enthalten können, einschließlich Leerzeichen, Tabulatoren, Zeilenumbrüche, einfache Anführungszeichen, doppelte Anführungszeichen, einfache Anführungszeichen mit Escapezeichen usw.! Betrachten Sie für einige schnelle Beispiele Verzeichnisse mit diesen Namen, die alle vollkommen legal sind:

  • "Keine solche Datei" (mkdir "No such file" )
  • "ls:kann nicht auf 'foo' zugreifen:Keine solche Datei oder Verzeichnis" (mkdir "ls: cannot access 'foo': No such file or directory" )
  • "Verzeichnis

    mit

    eingebettet

    Zeilenumbrüche" (mkdir $'directory\nwith\nembedded\newlines' )

Das erste ist ein unschuldiges Verzeichnis, das fälschlicherweise (von stdout) von grep erfasst wird . Die zweite wird ebenfalls fälschlicherweise erfasst, aber dann weiter in einen völlig anderen Pfad zerfleischt -- die existieren kann oder nicht! -- durch den sed Aussagen. Das dritte ist ein Beispiel dafür, was passiert, wenn Sie die Ausgabe von ls übergeben in zeilenorientierte Programme; wenn das Verzeichnis nicht existiert, ls wird dies in mehr als einer Zeile sagen, was wahrscheinlich dazu geführt hat, dass Sie zwei separate sed erhalten haben Aussagen!

Um "gute Pfade" -- solche, die existieren und lesbar sind -- von "schlechten Pfaden" zu unterscheiden, würde ich vorschlagen, das Array zu durchlaufen und jeweils neue Arrays zu erstellen.

for p in "${paths[@]}"
do
  if [ -r "$p" ]
  then
    goodpaths+=("$p")
  else
    badpaths+=("$p")
  fi
done

Sie können dann mit jedem Satz machen, was Sie wollen:

printf 'Good path: -->%s<--\n' "${goodpaths[@]}"
echo
printf 'Bad path: -->%s<--\n' "${badpaths[@]}"

Linux
  1. Welche Funktionen sind in Zsh und fehlen in Bash oder umgekehrt?

  2. Der beste Weg, um (aus einem Skript) zu erkennen, ob Software installiert ist?

  3. Ist es in Bash möglich, mit dem Lesen einer Datei von einem beliebigen Byte-Zähl-Offset zu beginnen?

  4. Bash-Array von Arrays?

  5. Welche Bash wird ausgeführt?

Bash-Arrays

Assoziatives Array in Bash

Wie erstelle ich ein Array eindeutiger Elemente aus einer Zeichenfolge/einem Array in Bash?

Führen Sie das Bash-Skript von der URL aus

Extrahiere die durchschnittliche Zeit aus ping -c

Konvertieren Sie eine Textzeichenfolge in Bash in ein Array