Como definir ícones de pastas de várias pastas automaticamente?

10

Como definir a primeira imagem de cada pasta como seu ícone de pasta?

A pergunta vinculada acima tem uma resposta que consiste em um script que está funcionando para mim. Só precisa de um pouco de melhoria.

O que isso faz?

Ele localiza arquivos com as extensões .jpg, .jpeg, .png, .gif, .icns, .ico e os define como o ícone da pasta na qual o arquivo foi encontrado. Funciona em várias pastas, recursivamente. Basicamente, ele tenta encontrar um arquivo de imagem dentro da pasta, e a primeira imagem encontrada é definida como um ícone de pasta. Funciona muito bem para muitos cenários, e configurar esse script geralmente é a primeira coisa que faço após a instalação nova (porque é incrível).

Qual é o problema?

Pode haver alguns diretórios que contêm muitos arquivos de imagem e o primeiro arquivo de imagem nesse diretório pode não ser adequado para ser o ícone da pasta.

O que deveria fazer?

Em vez de ser baseado em extensão, se ele se tornar baseado em nome de arquivo e direcionar um (por exemplo folder.png) ou vários (por exemplo albumart.png cover.png) nomes de arquivos, esse problema poderá ser resolvido.

ou melhor ainda, fazer com que ambas as abordagens funcionem em um único script

  • Localizar predefinido filenames
  • Se encontrado, defina-o como ícone da pasta e vá para a próxima pasta
  • Se NÃO for encontrado, encontre a extensão predefinida, defina-a como ícone da pasta e vá para a próxima pasta
Sumeet Deshmukh
fonte
Vamos continuar esta discussão no chat .
Sumeet Deshmukh

Respostas:

9

Eu ainda posso "elegante um pouco", mas abaixo estão as versões editadas das vinculadas.

Qual é a diferença?

Adicionei uma lista predefinida à seção principal:

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

e eu substituí:

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

por:

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

para que o script tente primeiro encontrar (arquivo) correspondências na lista specs, (somente) se não houver, ele pula para a busca pela extensão correspondente e executa o truque se encontrar uma imagem adequada.


1. A versão básica

Para ser usado com o diretório de destino como argumento:

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

Como usar

  1. Copie o script em um arquivo vazio, salve-o como change_icon.py
  2. No cabeçalho do script, edite, se quiser, a lista de extensões a serem usadas como imagens de ícone válidas. Defina também a lista preferida de nomes de arquivos.
  3. Execute-o com o diretório de destino como argumento:

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

É isso aí!


2. A opção editada com o botão direito do mouse, para ser usada como um script nautilus (clique com o botão direito do mouse)

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

Usar

  1. Crie, se ainda não existir, o diretório

    ~/.local/share/nautilus/scripts
    
  2. Copie o script em um arquivo vazio, salve-o ~/.local/share/nautilus/scriptscomo set_foldericons(sem extensão!) E torne-o executável .

  3. No cabeçalho do script, edite, se quiser, a lista de extensões a serem usadas como imagens de ícone válidas. Defina também a lista preferida de nomes de arquivos.
  4. Saia e entre novamente, e ele funciona.

Se, por algum motivo, você quiser redefinir os ícones dentro de uma pasta para os ícones padrão, use o script aqui

Jacob Vlijm
fonte
2
Você deve verificar se o URI do Nautilus realmente começa com file://. Em vez de replace("%20", " ")usar, você deve usar a decodificação URI adequada (por exemplo urllib.parse.unquote) e a codificação posterior ( urllib.parse.quote).
David Foerster
@DavidFoerster isso vai melhorar o desempenho do script, afinal? Eu tentei mudar subprocess.Popenpara subprocess.callmas em diretórios enormes com quase 700+ sub's, nem todos os ícones de pasta chnage.
Sumeet Deshmukh
@DavidFoerster thanks! mas urllib.parse.quotefunciona bem em um teste "seco", não no script. Precisa descobrir o porquê, mas deixando a versão de trabalho do script por enquanto.
Jacob Vlijm
@SumeetDeshmukh: Não, mas o script funcionará com URLs que contêm outros caracteres "especiais", além do caractere de espaço (U + 0020). Além disso, seria mais robusto contra dados errôneos ou falsos e o capturaria desde o início.
David Foerster
@JacobVlijm: O que acontece quando você tenta usá-lo no script? Mensagem de erro? Resultados inesperados? Funciona unquotecomo esperado?
David Foerster