Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen


  • Mod

    @siri sagte in [BASH: Tabelle mit 5 Spalten aus

    Das, was @wob sagte. ls -d */ und überhaupt ls soll man in Bash Scripts nie verwenden.

    Genau das hat wob ja gerade nicht vorgeschlagen. Lesen! Verstehen!



  • @SeppJ Danke!



  • @SeppJ muss ich dir jetzt etwas beweisen?

    Man soll eh kein bash -c in einem find machen. Warum wollt ihr auch eigentlich immer alles in eine einzige Zeile quetschen? Durch bestimmtes Quoting, indem du versuchst Bash-Ausdrücke in deinem -c Switch anzugeben wird das Argument zum ersetzen nicht von find übernommen, was daraus resultiert, dass auch genau der String {} als Argument verwendet wird.

    Man kanns sich halt auch einfacher machen. Du kannst dir eine Liste an Dateinamen erzeugen und einfach darüber iterieren, das ist dann zwar kein One-Liner mehr, jedoch viel übersichtlicher:

    mapfile -t files < <(find "$1" -maxdepth 3 -name '*.ending')
    
    for file in "${files[@]}"; do
        echo "${file}" "$(dirname "${file}")/.."
        # echo "${file}" "${file%/*}/.."
    done
    

    Du hast in deiner find Expression übrigens das Quoting rundherum $(...) vergessen. Und wie gesagt, bash -c sollte man bei find nicht machen.

    Bemerke auch das mapfile das ich verwendet habe, um ein Line-basiertes Array zu erstellen und ein Bash-internes Kommando ist und man solche Ausdrücke wie files=("$(find ...)") vermeiden soll.

    Was das Quoting angeht, kannst du diese einfach verschachteln, so wie in meinem Beispiel "$(dirname "${file}")/..". Viel mehr ist es nicht.

    EDIT: Außerdem würde ich hier auch kein dirname verwenden, sondern "${file%/*}/..". Das wäre noch pfiffiger und du ersparst dir obendrein noch einen Prozess.



  • Aber ... tief durchschnauf, das wäre doch jetzt ein Fall, in dem ein Bash-One-Liner nicht das beste Werkzeug für den Use-Case wäre. Ich stimme da dem SeppJ zu, und siri nur teilweise.

    @siri sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Außerdem würde ich hier auch kein dirname verwenden, sondern "${file%/*}/..".

    Wer soll denn das noch a) lesen können, b) lernen und c) gut finden ... das geht langsam in Richtung Kryptografie und Esoterik. Außerdem: Ist es robust? Also dürfen auch Leerzeichen usw. im Pfad vorkommen? Gibt es Edge-Cases?



  • @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Wer soll denn das noch a) lesen können, b) lernen und c) gut finden

    @ShredderButtonOn ja was hast du denn jetzt lieber, verschachtelte Quotes oder ein bisschen Syntax-Zucker mit nur einem normalen Quote?

    @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Außerdem: Ist es robust?

    Robust genug. Wenn du saubere Scripts schreibst, ist es immer sicher. Es gibt ein Makel, und zwar, dass der Dateinamen nicht mit einem / enden darf, was vielleicht eine valide Filesystem-Referenz wäre, aber zeigt, dass kein Code von Redundanz geplagt ist.

    @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Also dürfen auch Leerzeichen usw. im Pfad vorkommen?

    Ja

    @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Gibt es Edge-Cases?

    ja. Wenn dein Dateiname mit / endet, was von Redundanz zeugt, und eh nicht vorkommen dürfte. Deshalb soll man aufpassen, dass, wenn du hard-kodierte Dateipfäde in String-Variablen definierst, dass diese auch wenigstens sauber hard-kodiert, sind, also fp=/home/shredder/f.txt und nicht fp=/home/shredder/f.txt/.



  • @siri sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    ja was hast du denn jetzt lieber, verschachtelte Quotes oder ein bisschen Syntax-Zucker mit nur einem normalen Quote?

    Eine Indirektion weniger, ist immer besser ... dennoch finde ich das fast unübersichtlich ... aber das soll keine Kritik an dir sein, eher ein subjektives Empfinden.



  • @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    aber das soll keine Kritik an dir sein, eher ein subjektives Empfinden.

    Darin kritisierst du halt nicht mich, sondern Bash. Parameter expansion ist sauberer und um ein vielfaches schneller.



  • Hm, und was sagen die übrigen dazu? 🤔


  • Mod

    @ShredderButtonOn sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Hm, und was sagen die übrigen dazu? 🤔

    Parameterexpansion ist schon eine feine Sache, wenn man nur Effizienz betrachtet. Aber hat halt auch unerwartete Nachteile.

    Hier musste siri einige Verrenkungen machen, um es überhaupt nutzen zu können. Ist das noch effizient? Wahrscheinlich sogar ja, weil die Subprozesse und Pipes, die man dadurch spart, ganz schön teuer sind. Aber dann muss man wieder fragen, wen in so einem Anwendungsfall Effizienz im Mikrosekundenbereich interessiert.

    Ein weiterer, nicht offensichtlicher Nachteil ist, dass das manchmal auf unerwartete Art fehlschlagen kann. Das hier gezeigte ${file%/*} funktioniert hier nur, weil die Ergebnisse von find garantiert die richtige Form dafür haben. Wenn aber file=test.txt wäre (was ja ganz legitim ist, wenn test.txt im aktuellen Verzeichnis liegt), dann würde ${file%/*} zu nix expandiert, wohingegen dirname $file immer noch . wäre. Das heißt, hier hätte man als Zielpfad des mv dann statt ./.. auf einmal /... Ein katastrophaler Fehler, wenn jemals jemand den ersten Teil des Scripts abändert, so dass die Annahme nicht mehr gilt (zum Beispiel indem man die Dateinamen aus Nutzereingaben nimmt), ohne den kompletten Ablauf und alle Fallstricke der Expansion zu durchdenken, wo dirname die solidere Wahl gewesen wäre, weil es ohne Trickserei das ausdrückt, was man erreichen möchte.

    Shell-Tricks sind zwar schön und cool, aber man trickst sich damit auch gerne selbst aus, eventuell erst nach langer Zeit, wenn man vergessen hat, dass die Funktionsweise von einem Script, das man ändert, von solch einem Kniff abhängt. Ob die daraus folgenden Kopfschmerzen den Coolnessfaktor wert sind, muss man selber wissen. Produktiv in einer Umgebung, wo das verlässlich funktionieren muss, und wo noch andere Leute daran arbeiten, würde ich so etwas tunlichst vermeiden.



  • @SeppJ sagte in BASH: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    wen in so einem Anwendungsfall Effizienz im Mikrosekundenbereich interessiert.

    Es geht da nicht um Millisekunden. Wenn man den tatsächlichen Overhead messen würde, also abzüglich der ohnehin benötigten Zeit für das Dateiverschieben, bewegen wir uns wahrscheinlich im Mikro- oder gar im Nanosekundenbereich!

    @SeppJ Könntest du bitte im Titel dieses Themas "BASH" durch "Bash" ersetzen? Das liest sich besser.


  • Mod

    @SeppJ Könntest du bitte im Titel dieses Themas "BASH" durch "Bash" ersetzen? Das liest sich besser.

    Ich habe es mal für dich gemacht, aber der Threadersteller (hier also du) kann das auch. Dazu einfach den ersten Beitrag editieren; die Überschrift ist Teil dieses Beitrags.



  • @siri sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Man kanns sich halt auch einfacher machen. Du kannst dir eine Liste an Dateinamen erzeugen und einfach darüber iterieren, das ist dann zwar kein One-Liner mehr, jedoch viel übersichtlicher:

    ... und nicht in allen Fällen richtig.

    $ touch "testfile                     
    dquote> with 2 lines.ending"
    

    Und whoops 😉

    In wiederverwertbaren Scripten find immer mit -print0 benutzen.

    Oder eben gleich all diese Pitfalls vermeiden und eine "richtige" Programmiersprache verwenden. Wie gesagt, nichts gegen bash für kurze Progrämmchen - aber je mehr Logik man unterbringen will, desto weniger sinnvoll ist das in bash.



  • @wob sagte in [Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen]

    Oder eben gleich all diese Pitfalls vermeiden und eine "richtige" Programmiersprache verwenden. Wie gesagt, nichts gegen bash für kurze Progrämmchen - aber je mehr Logik man unterbringen will, desto weniger sinnvoll ist das in bash.

    Das ist ein Kriterium. Wenn der Zweck des Programms allerdings ist, hauptsächlich Kommandozeilen-Befehle abzusetzen, dann dürfen Bash-Skripte meiner Meinung nach auch gerne etwas länger sein. Dass man die in Shell-Skripten einfach so hinschreiben kann, anstatt die erstmal mit Strings zusammenzubauen oder gar mit Unterprozess-Funktionen zu arbeiten kann auch ein großer Vorteil sein.



  • @wob Dateinamen mit Newlines ignoriere ich bewusst in meinen Scripts. Ich mein auch, was für ein Held macht auch Newlines in Dateinamen.

    Immerhin kann man noch ein mapfile -t -d $'\0' filepaths < <(find ... -print0) machen. Aber ich glaube dieses -d ist in älteren Bash-Versionen nicht dabei. xargs hat auch so seine Tücken und die -exec Anwendung mit find finde ich nicht viel hübscher.


  • Mod

    @siri sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    @wob Dateinamen mit Newlines ignoriere ich bewusst in meinen Scripts.

    Du lebst gefährlich. Anders als viele andere Programme reagieren Shellscripts auf unerwartete Daten nicht mit Abstürzen, sondern arbeiten fröhlich mit den Mülldaten weiter (weil halt alles ein String ist, und irgendwie passt aller Müll in Strings). Da in solchen Scripts öfters recht mächtige Befehle aufgerufen werden (zum Erstellen/Kopieren/Verschieben/Löschen von Dateien), kann das ganz schön Schaden anrichten, wenn man da unerwarteten Müll als Argument nutzt. Dann wird aus rm ${directory}/* dann plötzlich rm /* und viel Spaß!



  • ... Seid doch froh, dass ihr nicht mit türkischen Datei-Encodings (non-ascii, die passen nicht in utf-8) kämpfen müsst 🙃



  • @SeppJ sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Dann wird aus rm ${directory}/* dann plötzlich rm /* und viel Spaß!

    Oder auch ganz toll:

    # delete the two user-specified files
    rm "$first_user_specified_file" "$second_user_specified_file"
    

    Was soll schon schief gehen? Vielleicht ist first_user_specified_file="-rf"?
    Oder man nennt eine Datei mal --. Ich wette, sehr sehr viele Scripte failen damit.

    @ShredderButtonOn sagte:

    non-ascii, die passen nicht in utf-8

    -v, bitte! Welche Zeichen können nicht in utf-8 kodiert werden? Die Behauptung klingt erstmal falsch.


  • Mod

    @wob sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    @SeppJ sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Dann wird aus rm ${directory}/* dann plötzlich rm /* und viel Spaß!

    Oder auch ganz toll:

    # delete the two user-specified files
    rm "$first_user_specified_file" "$second_user_specified_file"
    

    Was soll schon schief gehen? Vielleicht ist first_user_specified_file="-rf"?
    Oder man nennt eine Datei mal --. Ich wette, sehr sehr viele Scripte failen damit.

    Oh, die sind gut. Ich glaube, manche meiner eigenen Scripte sind dagegen nicht gefeilt. Muss ich mal prüfen. Und dann diese Art Parameter auf die Scripte der Kollegen loslassen.



  • @SeppJ sagte in Bash: Tabelle mit 5 Spalten aus Ordnernamen in einem Ordner erstellen:

    Ich glaube, manche meiner eigenen Scripte sind dagegen nicht gefeilt.

    Meine teils auch nicht, auch wenn ich es neuerdings immer versucht habe. Aber allgemein sind die mehr für mich selbst und ich weiß ja, was ich übergebe...
    Meiner Feile fehlt allerdings irgendwie das L 😉 (scnr)



  • Was die Genauigkeit angeht habe ich kein Problem damit wenn du den Pfad vorher entweder mit dirname oder realpath normalisierst. Und statt nen riesigen One-Liner mit find zu schreiben, kann man auch ein eigenständiges Bash-Skript schreiben, das alle Vorkehrungen trifft, um sowas wie Parents/Dateinamen/Extensions korrekt zu determinieren. Auch mit Parameter Expansion.


Anmelden zum Antworten