Как установить значки папок для нескольких папок автоматически?

10

Как установить первое изображение каждой папки в качестве значка папки?

На вопрос, связанный выше, есть ответ, состоящий из сценария, который работал для меня. Это просто нужно немного улучшить.

Что оно делает?

Он находит файлы с расширениями .jpg, .jpeg, .png, .gif, .icns, .ico и устанавливает их в качестве значка папки, в которой был найден файл. Работает на нескольких папках, рекурсивно. В основном он пытается найти файл изображения внутри папки, и первое найденное изображение устанавливается как значок папки. Он отлично работает для многих сценариев, и настройка этого скрипта - обычно первое, что я делаю после новой установки (потому что это потрясающе).

В чем проблема?

Там может быть несколько каталогов, которые содержат много файлов изображений, и первый файл изображения в этом каталоге может не подходить для значка папки.

Что это должно сделать?

Вместо того, чтобы основываться на расширении, если оно стало основанным на имени файла и предназначалось для одного (например folder.png) или нескольких (например albumart.png cover.png) имен файлов, тогда эта проблема могла бы быть решена.

или еще лучше, чтобы оба подхода работали в одном скрипте

  • Найти предопределенный filenames
  • Если найдено, установите его как значок папки и перейдите к следующей папке
  • Если НЕ найдено, найдите предопределенное расширение, установите его в качестве значка папки и перейдите к следующей папке.
Сумит Дешмукх
источник
Давайте продолжим эту дискуссию в чате .
Sumeet Дешмук

Ответы:

9

Я мог бы все еще "изобразить это немного", но ниже отредактированные версии связанных.

В чем разница?

Я добавил предопределенный список в раздел заголовка:

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

и я заменил:

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

по:

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

так что сценарий сначала пытается найти (файл) совпадения в списке specs(только), если их нет, он переходит к поиску совпадающего расширения и выполняет свою задачу, если находит подходящее изображение.


1. Базовая версия

Для использования с целевым каталогом в качестве аргумента:

#!/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))
                ])

Как пользоваться

  1. Скопируйте скрипт в пустой файл, сохраните его как change_icon.py
  2. В заголовке сценария отредактируйте, если хотите, список расширений, которые будут использоваться в качестве допустимых изображений значков. Также установите предпочтительный список имен файлов.
  3. Запустите его с целевым каталогом в качестве аргумента:

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

Это оно!


2. Отредактированная опция щелчка правой кнопкой мыши, которая будет использоваться в качестве скрипта nautilus (щелчок правой кнопкой мыши)

#!/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))
                ])

Использовать

  1. Создайте, если он еще не существует, каталог

    ~/.local/share/nautilus/scripts
    
  2. Скопируйте скрипт в пустой файл, сохраните его ~/.local/share/nautilus/scriptsкак set_foldericons(без расширения!) И сделайте его исполняемым .

  3. В заголовке сценария отредактируйте, если хотите, список расширений, которые будут использоваться в качестве допустимых изображений значков. Также установите предпочтительный список имен файлов.
  4. Выйдите и снова войдите, и это работает.

Если по какой-то причине вы хотите сбросить значки в папке на их значки по умолчанию, используйте скрипт здесь

Якоб Влейм
источник
2
Вы должны убедиться, что URI от Nautilus фактически начинается с file://. Вместо replace("%20", " ")вас следует использовать правильное декодирование URI (например urllib.parse.unquote) и более позднюю кодировку ( urllib.parse.quote).
Дэвид Фёрстер,
@DavidFoerster это все равно улучшит производительность скрипта? Я пытался перейти subprocess.Popenна, subprocess.callно в огромных каталогах с почти 700 + sub не все значки папок chnage.
Сумит Дешмух
@DavidFoerster спасибо! но urllib.parse.quoteотлично работает на "сухом" тесте, а не в скрипте. Нужно выяснить почему, но пока оставляем рабочую версию скрипта.
Джейкоб Влейм
@SumeetDeshmukh: Нет, но он заставит скрипт работать с URL-адресами, которые содержат другие «специальные» символы, кроме пробела (U + 0020). Кроме того, он будет более устойчивым к ошибочному или поддельному вводу и поймает его на раннем этапе.
Дэвид Фёрстер
@JacobVlijm: Что происходит, когда вы пытаетесь использовать его в сценарии? Сообщение об ошибке? Неожиданные результаты? Работает ли unquoteкак положено?
Дэвид Фёрстер