Sortieren Sie alle Dateien in einem Ordner unabhängig voneinander mit einer Ausgabedatei

498
Hashim

Ich habe mehrere Ordner, die zahlreiche Textdateien enthalten, die zwischen zehn und hundert liegen. Bei diesen Textdateien handelt es sich um einfache Datenbanken mit Millionen Zeilen, wobei jede Zeile einen einzelnen Datensatz enthält. Die darin enthaltenen Datensätze sind jedoch nicht sortiert und enthalten viele Duplikate. Ich möchte sie alle einzeln sortieren und dekomprimieren (dh unabhängig voneinander), aber meines Wissens sortkann ich nur eine verkettete Ausgabe aller Eingabedateien erzeugen. Das heißt, auch wenn mehrere Dateien angegeben werden, wird dies nur möglich sein eine Ausgabedatei erzeugen, die die kombinierten Ergebnisse all dieser Dateien enthält.

Wie kann ich alle Dateien im aktuellen Ordner sortieren, um für jede eine individuell sortierte Ausgabedatei zu erstellen ? Ich möchte auch, dass die Ausgabedateien in einem Unterordner innerhalb des aktuellen Verzeichnisses ausgegeben werden. Eine forSchleife ist die naheliegende Lösung für mich, aber ich frage hier für den Fall, dass es einen einfacheren Weg gibt, dies mit sortdem zu tun, dass ich nicht gestolpert bin oder vermisst habe. Mein bashWissen fehlt auch sehr, so dass, wenn eine forSchleife ist die einfachste Lösung, ich jemanden schätzen würde die beste Weg, um darüber zu gehen, anstatt mich viele Tage verbringen etwas Hacking zusammen, die noch kurz fallen würde, was ich tun möchte.

0
`sort -u` bietet eine einzige Liste der Datensätze. matzeri vor 6 Jahren 0
@matzeri Trollst du? Hashim vor 6 Jahren 0

1 Antwort auf die Frage

1
Kamil Maciorowski

Ja, das kannst du mit for. Auch wenn es "einen einfacheren Weg gibt, dies zu tun sort" (aber ich glaube nicht), ist dies auch ziemlich einfach:

# cd to the directory you want to process  mkdir sorted  for file in *;  do printf 'Processing %s\n' "$file" [ -f "$file" ] && sort -u "$file" > "./sorted/$file" done 

Anmerkungen:

  • for file in * verarbeitet keine Dateien in Unterverzeichnissen.
  • printfist nur um Fortschritt zu melden. Tatsächlich sollte es nach [ ... ](siehe unten) platziert werden, aber ich möchte den Code nicht zu kompliziert machen. Sie können die printfZeile einfach entfernen, wenn Sie möchten, dass das Ganze stumm bleibt.
  • [ -f "$file" ]prüft, ob $filees sich um eine reguläre Datei handelt. Bei dem allgemeinsten Muster (dh *) benötigen wir diese Bedingung, um zu vermeiden, dass sortdas sortedVerzeichnis als Argument verwendet wird (dies würde einen Fehler auslösen, harmlos, aber nicht elegant). Dieser Test wird höchstwahrscheinlich nicht benötigt, wenn Sie einen spezifischeren Globus wie *.txtoder *.dbanstelle von verwenden *(z. B. um eine Streudatei zu überspringen desktop.ini, die nicht verarbeitet werden sollte). In diesem Fall können Sie [ ... ] &&die Zeile auslassen und mit der Zeile beginnen sort(das Beibehalten der Zeile sollte jedoch nicht schaden).
  • sort unterstützt verschiedene Optionen, und Sie möchten möglicherweise einige davon verwenden, je nachdem, wie Sie sortieren müssen.

  • sort -uentdupliziert Einträge direkt nach dem Sortieren und ist bei Verwendung bereits sorteine weniger redundante Alternative zur Verwendung des uniqBefehls.

Wenn Sie Dateien nach Bedingungen auswählen mussten, die komplexer als ein einfacher Glob sind, ist es findvielleicht besser, mit zu beginnen. Für deine aktuelle Aufgabe forsollte es gut gehen.

Das sieht perfekt aus, vielen Dank. Es gibt einen Teil des Codes, auf den ich etwas verwirrt bin - woher kommt die [-f "$ file"] `? Zu welchem ​​Befehl gehört also der `-f`-Parameter und was genau bedeuten die eckigen Klammern? Ich habe diese Art von Syntax in einer Bash-Datei noch nicht gesehen, zumindest nicht in diesem Zusammenhang. Hashim vor 6 Jahren 0
Okay, ich habe hier meine Antwort gefunden, dass es auch den `test`-Befehl gibt: https://stackoverflow.com/questions/28036052/what-does-f-mea, aber was genau bedeutet dies? Das "[...]" ist eine Abkürzung für den Testbefehl? Hashim vor 6 Jahren 0
@Hashim Siehe `help [` in Bash. Kamil Maciorowski vor 6 Jahren 0
Unglücklicherweise gibt das keine anderen Informationen an, als zu sagen, dass es ein Synonym ist. Ich denke, das ist die einzige Antwort. Es gibt noch etwas - ich habe mich daran gewöhnt, `LC_ALL = C sort` zu tun, um einen normalerweise langsamen` sort'-Befehl viel schneller zu machen, indem er auf das Standardgebiet (US-Englisch) begrenzt wird. Kennen Sie eine Möglichkeit, dies in Ihren Code oben zu integrieren? Das einfache Hinzufügen vor "sort" führt zu einem `Syntaxfehler in der Nähe des unerwarteten Tokens &&`. Es ist kein großes Problem, wenn dies nicht möglich ist, aber es wäre schön, herauszufinden, ob dies möglich ist. Hashim vor 6 Jahren 0
Ich hoffe, es macht Ihnen nichts aus, aber ich habe ein paar kleinere Änderungen am Code vorgenommen, die ich für etwas weniger überflüssig halte. Fühlen Sie sich frei, sie zurückzusetzen, wenn es einen Grund für die ursprüngliche Codierung gab. Hashim vor 6 Jahren 0
@Hashim `[-f" $ file "] && LC_ALL = C sort ...` funktioniert für mich unter Debian. Kamil Maciorowski vor 6 Jahren 0
Trotzdem war ich etwas dicht. Ich hatte beschlossen, den Befehl zum Testen der Datei zu entfernen, hatte aber vergessen, was Sie darüber sagten, wie Sie die Zeile mit sort beginnen. Das gab mir folgendes: https://pastebin.com/hxs9xNBm. Ich vermute, dass ich davon ausging, dass das `&&` vom `printf'-Kommando aus angekettet würde, genau wie beim File-Test-Befehl. Gibt es einen Grund, warum dies nicht der Fall ist? Hashim vor 6 Jahren 0
@Hashim Ja. Wenn die Shell `printf 'analysiert, hat sie keinen Grund, sich auf die nächste Zeile zu freuen. Wenn die Shell auf Ihr & & trifft, wurde die Zeile mit `printf 'bereits analysiert und ausgeführt. Kamil Maciorowski vor 6 Jahren 1
Ah, ich verstehe, das macht Sinn. Es tut mir leid, dass ich Sie weiterhin damit belästige, aber ich verspreche Ihnen, dies ist die letzte Frage, die ich nach diesem Code stellen werde. : P Ich habe versucht herauszufinden, wie der fragliche Code geändert werden kann, um die sortierte Datei im selben Verzeichnis auszugeben, jedoch mit einem _sorted-Suffix am Ende. Ist das viel schwieriger? Ich kann an anderer Stelle keine Hilfe finden, weshalb ich Sie immer noch belästige. Bisher habe ich `LC_ALL = C sort -u" $ i ">>" ./$ i_sorted "`, aber aus irgendeinem Grund hört das auf mit `Ist ein Verzeichnis ', obwohl es für mich wie eine Datei aussieht und da ist kein solches Verzeichnis. Hashim vor 6 Jahren 0
Lassen Sie uns [diese Diskussion im Chat fortsetzen] (https://chat.stackexchange.com/rooms/83138/discussion-between-kamil-maciorowski-and-hashim). Kamil Maciorowski vor 6 Jahren 0