Jak automatycznie ustawić ikony folderów wielu folderów?

10

Jak ustawić pierwsze zdjęcie każdego folderu jako ikonę folderu?

Powyższe pytanie zawiera odpowiedź składającą się ze skryptu, który dla mnie działa. Potrzebuje tylko niewielkiej poprawy.

Co to robi?

Znajduje pliki z rozszerzeniami .jpg, .jpeg, .png, .gif, .icns, .ico i ustawia je jako ikonę folderu folderu, w którym plik został znaleziony. Rekurencyjnie działa na wielu folderach. Zasadniczo próbuje znaleźć plik obrazu w folderze, a pierwszy znaleziony obraz jest ustawiany jako ikona folderu. Działa świetnie w wielu scenariuszach, a konfiguracja tego skryptu jest zwykle pierwszą rzeczą, którą robię po świeżej instalacji (ponieważ jest niesamowita).

Jaki jest problem?

Może istnieć kilka katalogów, które zawierają dużo plików graficznych, a pierwszy plik obrazu w tym katalogu może nie nadawać się do bycia ikoną folderu.

Co powinien zrobić

Zamiast rozszerzenie oparte jeśli stało się nazwa pliku i ukierunkowane na podstawie jednego (na przykład folder.png) lub wielokrotne (np albumart.png cover.png) nazwy plików to ten problem może zostać rozwiązany.

lub jeszcze lepiej, aby oba podejścia działały w jednym skrypcie

  • Znajdź predefiniowane filenames
  • Jeśli znaleziono, ustaw go jako ikonę folderu i przejdź do następnego folderu
  • Jeśli NIE zostanie znaleziony, znajdź predefiniowane rozszerzenie i ustaw je jako ikonę folderu i przejdź do następnego folderu
Sumeet Deshmukh
źródło
Daj nam kontynuować tę dyskusję w czacie .
Sumeet Deshmukh

Odpowiedzi:

9

Mogę nadal „trochę to wyrafinować”, ale poniżej są edytowane wersje tych powiązanych.

Jaka jest różnica?

Dodałem predefiniowaną listę do sekcji głowy:

specs = ["folder.png", "cover.png", "monkey.png"]

i wymieniłem:

try:
    first = min(p for p in os.listdir(folder) 
                if p.split(".")[-1].lower() in ext)
except ValueError:
    pass

przez:

fls = os.listdir(folder)
try:
    first = [p for p in fls if p in specs]
    first = first[0] if first else min(
        p for p in fls if p.split(".")[-1].lower() in ext
        )
except ValueError:
    pass

więc skrypt najpierw próbuje znaleźć (plik) dopasowania na liście specs((tylko), jeśli nie ma, przeskakuje do wyszukiwania pasującego rozszerzenia i wykonuje lewę, jeśli znajdzie odpowiedni obraz.


1. Podstawowa wersja

Do użycia z katalogiem docelowym jako argumentem:

#!/usr/bin/env python3
import subprocess
import os
import sys

# --- set the list of valid extensions below (lowercase)
# --- use quotes, *don't* include the dot!
ext = ["jpg", "jpeg", "png", "gif", "icns", "ico"]
# --- set the list of preferred filenames
# --- use quotes
specs = ["folder.png", "cover.png", "monkey.png"]
# ---

# retrieve the path of the targeted folder
dr = sys.argv[1]

for root, dirs, files in os.walk(dr):
    for directory in dirs:
        folder = os.path.join(root, directory)
        try:
            fls = os.listdir(folder)
            first = [p for p in fls if p in specs]
            first = first[0] if first else min(
                p for p in fls if p.split(".")[-1].lower() in ext
                )
        except (ValueError, PermissionError):
            pass

        else:
            subprocess.Popen([
                "gvfs-set-attribute", "-t", "string",
                os.path.abspath(folder), "metadata::custom-icon",
                "file://"+os.path.abspath(os.path.join(folder, first))
                ])

Jak używać

  1. Skopiuj skrypt do pustego pliku i zapisz go jako change_icon.py
  2. W nagłówku skryptu edytuj, jeśli chcesz, listę rozszerzeń, które będą używane jako prawidłowe obrazy ikon. Ustaw także preferowaną listę nazw plików.
  3. Uruchom go z docelowym katalogiem jako argumentem:

    python3 /path/to/change_icon.py <targeted_directory>
    

Otóż ​​to!


2. Zmodyfikowana opcja kliknięcia prawym przyciskiem, która ma być używana jako skrypt nautilus (kliknięcie prawym przyciskiem)

#!/usr/bin/env python3
import subprocess
import os

# --- set the list of valid extensions below (lowercase)
# --- use quotes, *don't* include the dot!
ext = ["jpg", "jpeg", "png", "gif", "icns", "ico"]
# --- set the list of preferred filenames
# --- use quotes
specs = ["folder.png", "cover.png", "aap.png"]
# ---

def fix(path):
    for c in [("%23", "#"), ("%5D", "]"), ("%5E", "^"),
              ("file://", ""), ("%20", " ")]:
        path = path.replace(c[0], c[1])
    return path

# retrieve the path of the targeted folder
current = fix(os.getenv("NAUTILUS_SCRIPT_CURRENT_URI"))
dr = os.path.realpath(current)

for root, dirs, files in os.walk(dr):
    for directory in dirs:
        folder = os.path.join(root, directory)
        try:
            fls = os.listdir(folder)
            first = [p for p in fls if p in specs]
            first = first[0] if first else min(
                p for p in fls if p.split(".")[-1].lower() in ext
                )
        except (ValueError, PermissionError):
            pass

        else:
            subprocess.Popen([
                "gvfs-set-attribute", "-t", "string",
                os.path.abspath(folder), "metadata::custom-icon",
                "file://"+os.path.abspath(os.path.join(folder, first))
                ])

Używać

  1. Utwórz, jeśli jeszcze nie istnieje, katalog

    ~/.local/share/nautilus/scripts
    
  2. Skopiuj skrypt do pustego pliku, zapisz go ~/.local/share/nautilus/scriptsjako set_foldericons(bez rozszerzenia!) I spraw , aby był wykonywalny .

  3. W nagłówku skryptu edytuj, jeśli chcesz, listę rozszerzeń, które będą używane jako prawidłowe obrazy ikon. Ustaw także preferowaną listę nazw plików.
  4. Wyloguj się i zaloguj ponownie, i to działa.

Jeśli z jakiegoś powodu chcesz zresetować ikony w folderze do domyślnych ikon, użyj skryptu tutaj

Jacob Vlijm
źródło
2
Powinieneś sprawdzić, czy URI z Nautilus faktycznie zaczyna się file://. Zamiast tego replace("%20", " ")należy użyć właściwego dekodowania URI (np. urllib.parse.unquote) I późniejszego kodowania ( urllib.parse.quote).
David Foerster
@DavidFoerster, czy to i tak poprawi wydajność skryptu? Próbowałem zmienić subprocess.Popenna, subprocess.callale w ogromnych katalogach z prawie 700+ sub, nie wszystkimi ikonami folderów.
Sumeet Deshmukh
@DavidFoerster dzięki! ale urllib.parse.quotedziała dobrze na „suchym” teście, nie w skrypcie. Musisz dowiedzieć się, dlaczego, ale na razie pozostawiając działającą wersję skryptu.
Jacob Vlijm,
@SumeetDeshmukh: Nie, ale sprawi, że skrypt będzie działał z adresami URL, które zawierają inne „specjalne” znaki oprócz znaku spacji (U + 0020). Dodatkowo byłby bardziej odporny na pomyłki lub fałszywe dane wejściowe i wychwytywałby go wcześnie.
David Foerster,
@JacobVlijm: Co się stanie, gdy spróbujesz użyć go w skrypcie? Komunikat o błędzie? Nieoczekiwane wyniki? Czy unquotedziała zgodnie z oczekiwaniami?
David Foerster,