Erweiterte Dateiattribute mit Zenity in Thunar einbinden

  Ralf Hersel   Lesezeit: 7 Minuten  🗪 4 Kommentare

Ein sinnfreier Versuch, erweiterte Dateiattribute mit Zenity in Thunar zu integrieren.

erweiterte dateiattribute mit zenity in thunar einbinden

Ich bin sehr enttäuscht. Jetzt wollte ich einen schönen Artikel darüber schreiben, wie man die erweiterten Dateiattribute mit den einfachen Zenity-Dialogen im Dateimanager Thunar einbindet, da schreibt ein Leser, dass die Attribute bei einer Änderung der Datei überschreiben werden. Um zu verstehen, worum es geht, solltet ihr den oben erwähnten Artikel lesen.

Damit ich nicht vergebens daran gearbeitet habe, schreibe ich diesen Artikel trotzdem, um meinen Misserfolg für die Nachwelt zu erhalten. Die Idee war es, die erweiterten Dateiattribute direkt aus einem Dateimanager (Thunar oder andere) bearbeiten zu können. Dazu habe ich zwei Skripte geschrieben und diese in Thunar eingebunden. Das erste Skript erlaubt es, einer Datei beliebige Tags und Werte zuzuordnen; mit dem zweiten Skript kann man diese Attribute anschauen. Ein drittes Skript hätte das Löschen der Attribute erlaubt. Aufgrund der oben genannten Gründe habe ich das nicht gemacht.

Fast alle Dateimanager erlauben Erweiterungen durch den Aufruf von Skripten. Das können Shell-Skripte oder Python-Programme oder sonst etwas sein. Die Dateimanager übergeben dabei diverse Parameter, wie den Pfad der ausgewählten Datei, oder eine Liste von Dateien und noch mehr. Die Dokumentation für Thunar findet ihr hier und für Nautilus dort. Warum ich als GNOME-Anwender Thunar statt Nautilus verwende, könnt ihr in diesem Beitrag lesen.

Genug der Vorworte. Hier sind die zwei Skripte:

Beim Ersten handelt es sich um ein Shell-Skript, welches setfattr aufruft, um im Namespace user ein neues Attribut zu erzeugen und mit einem Wert zu belegen. So sieht es aus:

#!/bin/bash
# Thunar extension
# add attribute/value to file

result=$(zenity --title "Attribute" --forms --text "Set Attribute" --add-entry "Attribute" --add-entry "Value")
attribute=$(echo $result | cut -d "|" -f 1)
value=$(echo $result | cut -d "|" -f 2)
setfattr -n user.$attribute -v $value $1

Darin wird ein Zenity-Formular mit zwei Feldern aufgerufen: Name des Attributs und Wert des Attributs. Das Skript heisst setattr.sh und kann in die Benutzerdefinierten Aktionen aufgenommen werden. Dem Skript übergibt Thunar mit dem Parameter %f die ausgewählte Datei. Mit %F können auch mehrere ausgewählte Dateien übergeben werden.

Dann findet man in Thunar nach einem Rechtsklick auf eine Datei den Menüpunkt Set Attribute vor, mit dem sich ein Dialog öffnet, in dem Attributname und Wert eingetragen werden können (siehe Titelbild). Die Vergabe von Attributen kann man weiterführen; im Beispiel habe ich Farbe, Grösse und Verwendung eingetragen.

Das zweite Skript kümmert sich um die Anzeige der Attribute für eine Datei. Dieses heisst Show Attributes und erscheint ebenfalls im Kontextmenü einer Datei in Thunar. Man könnte es erweitern, sodass Attribute für mehrere ausgewählte Dateien gesetzt werden können. Im ersten Ansatz wollte ich dieses Skript auch als Shell-Skript implementieren. Beim Parsen von komplizierten Strings ist ein Shell-Skript keine gute Empfehlung; da ist man mit Python besser beraten. Daher habe ich das zweite Skript in Python geschrieben. An dieser Stelle geht ein herzlicher Dank an die GNU/Linux.ch-Community für ihre Unterstützung.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Thunar extension
# show attributes/values of a file

import subprocess

def shell(command):                                                             # run shell command and return the output
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
    stdout = p.stdout
    return stdout    

def main(args):
    lines = shell(f'getfattr -d {args[1]}')                                     # get file attributes and values
    next(lines)                                                                 # skip first line (contains file name)
    content = []
    for line in lines:
        line = line.decode()                                                    # convert to something readable
        if not line.strip(): continue                                           # skip the empty last line
        entry = line.strip().split('=')                                         # kick out white chars and convert to list
        attribute = entry[0].replace('user.', '')                               # remove leading namespace
        value = entry[1].replace('"', '')                                       # remove surrounding "
        content.append([attribute, value])
    all = ''
    for i in content:                                                           # flatten the list to one space separated string
        all += ' '.join(i)
        all += ' '
    shell(f'zenity --title "Attribute" --list --column "Attribute" --column "Value" {all}')
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Die genaue Erklärung aller Schritte im Skript führt wohl etwas zu weit. Daher nur ganz kurz. Die Funktion shell führt ein Shell-Kommando aus und liefert dessen Ausgabe zurück. Getfattr holt die Attribute der Datei. Im Original sieht das so aus:

getfattr -d test_1.txt

# file: test_1.txt
user.Farbe="rot"
user.Grösse="37"
user.Verwendung="Artikel"

Bei der Ausgabe sieht man gut, dass einiges an Parsing nötig ist, um zu den Strings: Farbe und rot zu gelangen. Im Gegensatz zum Shell-Skript ist das in Python kein Problem. Der Zenity Listendialog erwartet eine Leerzeichen-separierte Liste aller Werte in einem String. Das ist die Variable all im Skript. Wie das Ergebnis aussieht, seht ihr im Titelbild. Das Skript nimmt die Shell-Ausgabe entgegen, iteriert über die Zeilen der Ausgabe, schält die Attribute und Werte aus den Zeilen heraus und schreibt diese in die Liste content. Die Liste wird in der zweiten For-Schleife flach geklopft, damit ein kompletter Attribute-Werte-String entsteht, den Zenity gerne haben möchte.

Ich denke, ihr geht mit mir einig, dass diese Übung in Shell-Skript viel schwieriger gewesen wäre.

Man könnte noch ein drittes Skript erstellen, mit dem sich Attribute löschen lassen. Der Befehl dafür lautet:

setfattr -x user.$1 $2

Für die Umsetzung könnte man das zweite Skript wiederverwenden und den Löschbefehl für eine ausgewählte Zeile erweitern. Doch dazu wird es nicht kommen, weil die ganze Geschichte aus zweierlei Hinsicht hoffnungslos ist:

  1. Damit das Taggen von Dateien im Dateimanager zu einer hilfreichen Funktion wird, müssten die Attribute und Werte als Spalte integriert werden, sodass man sie sofort sehen und damit arbeiten kann. Zum Beispiel Sortieren und Suchen.

  2. Die Tatsache, dass die erweiterten Dateiattribute beim Ändern einer Datei verloren gehen, macht die Sache überflüssig. Da frage ich mich, warum es sie überhaupt gibt.

Trotz der Sinnlosigkeit hoffe ich, dass euch der Artikel ein wenig Wissen und Praxis vermittelt hat. Es gibt viele Möglichkeiten, den eigenen Dateimanager mit Skripten zu erweitern. Und vielleicht werden wir eines Tages ein Dateisystem erblicken, das Tagging nativ unterstützt.

Update

Beachtet bitte die Kommentare, in denen erklärt wird, dass es an den Anwendungen liegt, ob Dateiattribute behalten oder überschrieben werden. Somit handelt es sich nicht um ein Problem des Dateisystems, sondern wie die Anwendungen mit Dateien umgehen.

Tags

Thunar, Zenity, Dateiattribute, Tags, Shell-Skript, Python

s3nnet
Geschrieben von s3nnet am 2. Februar 2023 um 13:07

Funktioniert Dolphin nicht auch unter Gnome? Der kann doch Tagging, meine ich.

Jens T.
Geschrieben von Jens T. am 2. Februar 2023 um 14:03

Das Problem ist nicht das Ändern an sich, denn dabei wird kein Attribut überschrieben, sondern dass viele Anwendungen beim Speichern neue Dateien erstellen, die alte Datei löschen und die neue Datei entsprechend umbenennen. Das kann ja durchaus legitim sein, da man dann immernoch die alte Datei hat, wenn etwas beim Speichern der neuen schief gehen sollte. Auf der anderen Seite hat man schon Glück, wenn dabei wenigstens die Erstellungszeit übernommen wird. Die Anwendungsentwickler müssten sich darum kümmern, bei solchen einem Vorgehen auch die Attribute für die neue Datei zu übernehmen. Realistisch ist diese Forderung wohl leider nicht.

kamome
Geschrieben von kamome am 5. Februar 2023 um 13:59

Realistisch ist diese Forderung wohl leider nicht.

Ja, zumal nicht alle Dateisysteme die Attribute unterstützen und sie beim einfachen Kopieren ohnehin nicht erhalten bleiben – ist also leider auch ohne „böse“ Editoren schon sehr anfällig. Wäre toll, wenn es solche Attribute gäbe, die jedoch fest in die Datei integrierbar wären (und nicht im Dateinamen, was für mich ein nicht gangbarer Hack ist).

Michel
Geschrieben von Michel am 7. Februar 2023 um 20:39

Ixh glaube, das das hier ein typisches Problem von Linux ist, die Dateisysteme können so vieles aber einiges wird niemals genutzt weil es entweder kein Werkzeug gibt dass sich an gewisse regeln hält oder es ist zu schwirig oder Problematisch sich an die Regeln zu halten.

Kann es sen, dass all die Programmierer von Anwendungen die Dateien öffnen und Bearbeiten tatsächlich noch alle schritte die dazu notwendig sind noch selber Programmieren müssen?

Datei zum lesen öffnen, änderungen verfolgen und allenfalls kommunizieren. Datei-hash erstellen und Datei-Backup erstellen und sperren wenn man bearbeiten möchte. Dann Datei Speichern, der Anwendung einen integrationscheck ermöglichen und bei Erfolg die Kopie löschen. Im idealfall wird immer auch gleich ein file-hash als erweitertes Atrribut geschrieben.

Muss das den jeder Entwickler einer Applikation diese Schritte selber programmieren?