¿Cómo puedo cambiar un icono de archivo o carpeta usando la Terminal?

¿Cómo puedo cambiar o configurar el ícono de un archivo o carpeta, en la terminal, necesito usar un lenguaje de secuencias de comandos?

Tenga en cuenta que no escala bien. Intenté aplicar íconos a muchos directorios en un directorio: Finder funcionó muy lento.

Respuestas (12)

Necesitarás las herramientas de desarrollo instaladas y, luego, lo siguiente podría funcionar. Esto toma el gráfico icon.pngy lo aplica a file.ext.

# Take an image and make the image its own icon:
sips -i icon.png

# Extract the icon to its own resource file:
/Developer/Tools/DeRez -only icns icon.png > tmpicns.rsrc

# append this resource to the file you want to icon-ize.
/Developer/Tools/Rez -append tmpicns.rsrc -o file.ext

# Use the resource to set the icon.
/Developer/Tools/SetFile -a C file.ext

# clean up.
rm tmpicns.rsrc
# rm icon.png # probably want to keep this for re-use.
Genial, es justo lo que queria.
Tengo problemas Rez -appendcuando trabajo con .aviarchivos. ### Rez - Fatal error trying to open the resource file "Video.avi" for writing.¿alguna idea?
Curiosamente, también hizo que el archivo no pudiera aceptar un nuevo icono a través del método de copiar/pegar Obtener información.
¿Hay alguna restricción en el tamaño del icono? Si utilizo un jpg grande (1024x768), se cambiará el tamaño a algo realmente pequeño. ¿Puedo conservar su tamaño original de alguna manera?
@nuc OS X admite un tamaño máximo de ícono de 512x512, por lo que no veo ningún sentido (bueno, tal vez más que para el futuro) guardarlo más grande. Y mientras está en la línea de comandos, puede cambiar el tamaño de la imagen a 512, por ejemplo, con sorbos: sips -Z 512 image.png --out smaller-image.png(aunque si desea tener control sobre los algoritmos de remuestreo, tal vez un software de procesamiento de imágenes sea una mejor idea).
Tenga en cuenta que en las versiones recientes de OSX, las herramientas de desarrollo están en $PATH(stubs en los /usr/binque se sabe dónde encontrar las herramientas reales), y /Developer/Toolsya no, por lo que debe invocarlas solo por sus nombres de archivo; es decir, en el caso que nos ocupa, como justo Rezy DeRez.
macOS admite archivos de iconos cuadrados con resoluciones de hasta 1024x1024
¡Muchas gracias hombre! Estuve buscando esto desde muchas veces...

Con el beneficio de varios años de retrospectiva:

La respuesta de user588 y la respuesta de koiyu funcionan bien, pero dependen de utilidades ( Rez, DeRezy SetFile) que:

  • no se instalan de forma predeterminada (vienen con Xcode o las utilidades de línea de comandos del desarrollador)
  • ahora están en desuso ( Rezy DeRez, porque se relacionan con Carbon)

osxiconutils parece interesante, pero ya no compilará (a partir de macOS 10.10.4) .


Por lo tanto, he creado CLIfileicon , que debería funcionar en una máquina OSX prístina (sin requisitos previos) ; es un script de Bash basado principalmente en xattry xxdun script de Python incrustado que llama a Cocoa, cortesía de esta útil respuesta .

Permite configurar/eliminar/extraer íconos personalizados para/desde archivos o carpetas , incluso en volúmenes APFS en macOS 10.13 (High Sierra).

Puedes instalarlo de la siguiente manera:

  • Si tienes Homebrew instalado:brew install fileicon

  • Si tiene instalado Node.js, desde el registro npm , con
    [sudo] npm install -g fileicon

  • De lo contrario:

    • Descargue la CLI como fileicon(este enlace permanecerá actualizado).
    • Hazlo ejecutable con chmod +x fileicon.
      • Muévalo o vincúlelo a una carpeta en su correo electrónico $PATH, como /usr/local/bin(requiere sudo).

Aquí está la información de uso; para obtener información completa, consulte el manual :

$ fileicon -h

Set a custom icon for a file or folder:

    fileicon set      <fileOrFolder> <imageFile>

 Remove a custom icon from a file or folder:

    fileicon rm       <fileOrFolder>

 Get a file or folder's custom icon:

    fileicon get [-f] <fileOrFolder> [<iconOutputFile>]

 Test if a file or folder has a custom icon:

    fileicon test     <fileOrFolder>

 -q ...  silence status output

 Standard options: --help, --man, --version, --home
@Slomojo: [En respuesta a un comentario eliminado desde entonces] Entiendo que no todo el mundo tiene o quiere instalar Node.js, es por eso que el enlace de descarga directa también está allí (consulte el elemento de lista 'De lo contrario:' en mi respuesta) - es un script Bash autónomo (lo único que se pierde al instalar de esta manera es la instalación de la página del manual, pero puede obtener una representación de texto sin formato de la página del manual con fileicon --man).
@Slomojo: [En respuesta a un comentario eliminado] En cuanto a por qué se ofrece la instalación a través de npm: descubrí que el ecosistema npm es mi administrador de paquetes favorito en general, y he publicado una serie de scripts multiplataforma CLI basadas allí que no están relacionadas con Node.js. También creé un instalador de nivel de usuario de un solo comando para npm (a través de n y Node.js) que facilita el uso de npm incluso para las personas que no tienen ningún interés en Node.js: curl -L http://git.io/n-install | bash.
Esta es una buena solución de trabajo lista para usar. +1
Esto ya no funciona en 10.10. El proyecto se ha movido a github: github.com/sveinbjornt/osxiconutils si desea buscar una actualización.
@PatNiemeyer: Gracias, actualicé el enlace osxiconutils, pero tenga en cuenta que esta respuesta es sobre la utilidadfileicon , que aún funciona (y, de hecho, se creó, porque osxiconutilsya no funciona). Actualicé la respuesta para que quede más claro. .
Me doy cuenta de que estoy unos años por detrás de todos los demás en este hilo, pero solo quería mencionar que descubrí esto hoy y es genial. ¡Gracias por hacerlo! 👍
funciona muy bien

Casi comencé una recompensa por esto, porque no logré cambiar el ícono de una carpeta usando la respuesta de @ mankoff . Pero encontré una solución.


Para cambiar el ícono de la carpeta, no apunta Rez -append tmp.rsrca la carpeta sino a un Icon\rarchivo especial dentro de la carpeta. Si no ha configurado un icono personalizado en la carpeta antes, es probable que el archivo no exista, pero Rezlo crea sobre la marcha. Al eliminar el Icon\rarchivo, se eliminará el icono personalizado, por lo que, para evitar accidentes, es bueno ocultarlo.

Estas son las modificaciones a la respuesta de mankoff:

# Append a resource to the folder you want to icon-ize.
Rez -append tmpicns.rsrc -o $'myfolder/Icon\r'

# Use the resource to set the icon.
SetFile -a C myfolder/

# Hide the Icon\r file from Finder.
SetFile -a V $'myfolder/Icon\r'
¿Y para un archivo? Tenga en cuenta mi comentario sobre: ​​archivos avi
@slomojo lo siento, pero no puedo replicar el error que obtiene, solo probé la solución de mankoff con un archivo .avi. ¿Volver a verificar los permisos de archivo y los comandos que ingresó?
Lo intentaré de nuevo, tal vez cometí un error antes.
Estoy tratando desesperadamente de hacer esto para una memoria USB. Todos los comandos "funcionan" en el sentido de que no devuelven errores, pero todavía me queda una memoria USB con un ícono sin cambios. Cualquier pensamiento y estaría eternamente agradecido!

Además de Ruby, aquí hay una versión de Python:

#!/usr/bin/env python
import Cocoa
import sys

Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(Cocoa.NSImage.alloc().initWithContentsOfFile_(sys.argv[1].decode('utf-8')), sys.argv[2].decode('utf-8'), 0) or sys.exit("Unable to set file icon")

./set-image.py image.png myfile

Python que está preinstalado en Mac OS ya tiene PyObjC, por lo que no tiene que instalar ningún paquete.

Agregué la decodificación de UTF-8 a Unicode; de ​​lo contrario, el script no funcionaría con nombres de archivo que no sean ASCII. También se agregó la verificación del valor de retorno, si no se establece el ícono, se generará un código de retorno de 1.
¿Hay alguna forma en que podamos especificar que el icono no tenga la relación de aspecto modificada? Funciona muy bien, pero los archivos de imagen se reforman en un cuadrado. ¡Gracias!
No encontré exactamente la respuesta, pero cuadrar las imágenes con relleno transparente de antemano funcionó bien: stackoverflow.com/questions/12179342/…
Entiendo que en el lanzamiento de macOS Big Sur, se eliminará python. ¿Esto todavía funcionaría?

Consulte setfileicon(código fuente) , una utilidad creada por Damien Bobillot.

Descargue el binario aquí: http://maxao.free.fr/telechargements/setfileicon.gz

Después de descomprimir el archivo, hágalo ejecutable:

chmod +x setfileicon

Entonces puedes usarlo de la siguiente manera:

./setfileicon "my-icon.icns" "my-file-or-directory"
Gracias por eso, muy útil de hecho. Por cierto, estoy editando el método GUI para reducir el ruido.
Desafortunadamente, la mayoría del código ahora está en desuso.

Tengo un proyecto de github en el que creo "gotas" de AppleScript a partir de scripts [shell/bash, python, perl, ruby, etc.] que toman rutas de archivo como argumentos. Escribí esta función bash para cambiar el ícono de una carpeta (porque los paquetes de AppleScript son carpetas con una extensión .app).

replace_icon(){
    droplet="$1"
    icon="$2"
    if [[ "$icon" =~ ^https?:// ]]; then
        curl -sLo /tmp/icon "$icon"
        icon=/tmp/icon
    fi
    rm -rf "$droplet"$'/Icon\r'
    sips -i "$icon" >/dev/null
    DeRez -only icns "$icon" > /tmp/icns.rsrc
    Rez -append /tmp/icns.rsrc -o "$droplet"$'/Icon\r'
    SetFile -a C "$droplet"
    SetFile -a V "$droplet"$'/Icon\r'
}

Una vez definida, llamas a la función con 2 argumentos:

replace_icon /path/to/AppleScript.app /path/to/icon.png

o

replace_icon /path/to/AppleScript.app http://i.imgur.com/LmUvWqB.png

Como puede ver, el segundo argumento puede ser una imagen en su sistema o una URL.

NOTA: Esa locura $'/Icon\r'que hago es porque el nombre del archivo Icon termina con un retorno de carro literal\r . Compruébelo usted mismo con:

find my-applescript.app -maxdepth 1 | less -U

Suponiendo que ya tenemos el archivo icns. Cree un archivo de recursos temporal que apunte al archivo icns:

$ echo "read 'icns' (-16455) \"Icon.icns\";" >> Icon.rsrc

Agregue el archivo de recursos como valor del atributo extendido "com.apple.ResourceFork" a un archivo:

$ Rez -a Icon.rsrc -o FileName.ext

Mostrar el icono del archivo:

$ SetFile -a C FileName.ext

Agregue el archivo de recursos como valor del atributo extendido "com.apple.ResourceFork" a un archivo de icono mágico dentro de la carpeta actual:

$ Rez -a Icon.rsrc -o Icon$'\r'

Mostrar el icono de la carpeta actual:

$ SetFile -a C .

Oculte el archivo del ícono mágico dentro de la carpeta actual (presione ⇧⌘. para mostrar/ocultar archivos ocultos en Finder):

$ SetFile -a V Icon$'\r'

Detalles adicionales

Los datos del icono se almacenan como valor del atributo extendido "com.apple.ResourceFork" (el comando de terminal "xattr -p com.apple.ResourceFork FileName.ext" imprime el valor). Para una carpeta hay un archivo mágico (que está vacío y oculto) Icon$'\r'dentro de la carpeta. Para extraer datos de iconos del atributo extendido "com.apple.ResourceFork" en un archivo de recursos de texto sin formato (del que conocemos el identificador de tipo icns correcto "-16455"):

$ DeRez -only icns FileWithIcon.ext > Icon.rsrc
$ DeRez -only icns /Folder/With/Icon/Icon$'\r' > Icon.rsrc

En macOS 10.13, el comando High Sierra $ sips -i ImageFile.icns/png/jpggenera el error "--addIcon ya no es compatible". Cambie "-i" significa "--addIcon" como atributo extendido "com.apple.ResourceFork" en este archivo usando el contenido de este archivo de imagen.

#<stdin>:1: ### /Applications/Xcode.app/Contents/Developer/usr/bin/Rez - SysError 0 durante la lectura.

Otra opción es usar MacRuby:

/usr/local/bin/macruby -e 'framework "Cocoa";NSWorkspace.sharedWorkspace.setIcon(NSImage.alloc.initWithContentsOfFile("/tmp/a.png"),forFile:"/tmp/file",options:0)'

Puede descargar un instalador para MacRuby desde http://macruby.org .

El enlace, y MacRuby, aparentemente ahora están muertos; Aparentemente, MacRuby fue reemplazado por el RubyMotion comercial basado en suscripción .

Por extraño que parezca, la mejor solución parece ser no usar las propias herramientas de Apple sino el código de Python porque tiene varias ventajas que no están limitadas por:

  • resolución del archivo de salida
    (funciona hasta 1024x1024)
  • formato de archivo de entrada
    (probado con ICNS y PNG)
  • permisos para instalar
    (definirlo como una función)

Actualizar

Ahora (en macOS Sierra) la respuesta de @koiyu parece funcionar, por lo que podría usar este dos líneas para copiar el ícono de una carpeta de origen a su carpeta de destino:

#!/bin/sh

DeRez -only icns $1/Icon$'\r' > icon.rsrc; Rez -a icon.rsrc -o $2/Icon$'\r'
SetFile -a C $2; SetFile -a V $2/Icon$'\r'; rm icon.rsrc
¡Bienvenido a Ask Different! Esto parece que sería mejor como un comentario. Sé que aún no tienes los puntos requeridos, pero le pedí a alguien que tenga el poder que venga a echar un vistazo. Además, he escrito un Applescript que hace todo esto por usted en un paquete ordenado, vea mi respuesta a una pregunta similar sobre este SE.
Sí, lo intenté pero no pude hacerlo. Además, creo que la segunda parte de su comentario sería mejor como respuesta, ya que no está relacionada con la primera.

Al igual que la solución de Python que usa PyObjC, resulta que se puede hacer solo con AppleScript (que no está obsoleto en 10.15 Catalina, a diferencia de Python y otros lenguajes de secuencias de comandos).

Encontré un ejemplo de cómo hacer esto en GitHub aquí:

conjunto-buscador-icono

#!/usr/bin/env osascript

use framework "AppKit"

--------------------------------------------------------------------------------
# PROPERTY DECLARATIONS:
property this : a reference to current application
property NSWorkspace : a reference to NSWorkspace of this
property NSImage : a reference to NSImage of this

--------------------------------------------------------------------------------
# IMPLEMENTATION:
on run argv
  set icon to item 1 of argv
  set target to item 2 of argv

  setIcon to icon for target
end run
--------------------------------------------------------------------------------
# HANDLERS:
to setIcon to iconPath for filePath
  set sharedWorkspace to NSWorkspace's sharedWorkspace()
  set newImage to NSImage's alloc()
  set icon to newImage's initWithContentsOfFile:iconPath

  set success to sharedWorkspace's setIcon:icon forFile:filePath options:0
end setIcon

AppleScript no es fácil de leer, pero aparentemente es posible acceder al código de Objective-C para hacer esto a través del marco AppKit.

Eso es genial. Muchas gracias. Incluso pude ejecutar este script desde Java-Code y funciona perfectamente bien.

En la versión reciente de macOS (10.14), sips -i icon.pngobtendrá un --addIcon is no longer supportederror.

También necesita herramientas de desarrollo instaladas. Esto usa el gráfico Icon.pngy lo aplica file.ext, al igual que la respuesta de user588 :

# Covert Icon.png to tmpicons.icns:
sips -s format icns Icon.png --out tmpicns.icns

# Create temporary resource file which points to tmpicons.icns:
echo "read 'icns' (-16455) \"tmpicns.icns\";" >> tmpicns.rsrc

# append this resource to the file you want to icon-ize.
Rez -a tmpicns.rsrc -o file.ext

# Use the resource to set the icon.
SetFile -a C file.ext

# Clean up
rm tmpicons.icns && rm tmpicns.rsrc
Me pongo Error: Unable to write image to file /Users/uname/tmpicns.icns.4rzX6en el primer comando. Incluso intento con sudo, no funciona
Tengo el mismo problema que @leetbacoon. ¿Alguien sabe por qué?
@leetbacoon Consulte blog.macsales.com/… para obtener información sobre cómo convertir una carpeta de conjunto de iconos en un archivo icns. Si necesita crear mediante programación la carpeta del conjunto de iconos y llenarla con archivos png, use sips -z x x input.png -o output.pngdonde x es la altura y el ancho de la imagen, respectivamente. Esto creará una copia de input.png con la altura y el ancho especificados. Luego, solo asegúrese de que el archivo de salida esté dentro de la carpeta iconset.
Gracias por avisarme @PeterSchorn.

Hay algún tipo de error (que ocurre en las carpetas dentro de la sincronización de iCloud) con el cambio de íconos de "carpetas" ni de archivos, por fin en Catalina: cuando el ícono cambia, la interfaz de usuario no actualiza la carpeta con el nuevo ícono cuando tenga uno mayor. Entonces, la segunda vez que configura un ícono, no se actualiza todas las veces. Aunque lo hagas manualmente con cmd+i y pegando como icono una imagen previamente copiada, iCloud se vuelve loco con esto.

Al buscar una solución alternativa, encontré esta pequeña solución (no es ideal pero funciona): - esto está en JXA Javascript para automatización

function makeIcon(theFolder, theFile) {
    var img = $.NSImage.alloc.initByReferencingFile( theFile );
    var updateUUID = newUUID()+".txt";
    terminal("echo -n > "+ sanityzeForBash(theFolder+"/Icon\r") );
    terminal("rm "+ sanityzeForBash(theFolder+"/Icon\r") ); 
    writeTextFile(theFolder+"/"+updateUUID, "_"); 
    $.NSWorkspace.sharedWorkspace.setIconForFileOptions(img, theFolder, 0);
    delay(1);
    terminal("rm "+ sanityzeForBash(theFolder+"/"+updateUUID) );
}

function writeTextFile(fileName, text) {
    var file = app.openForAccess(Path(fileName), { writePermission: true })
    app.setEof(file, { to: 0 });
    app.write( getProperties(text) +"\n\r", { to: file, startingAt: app.getEof(file) })
    app.closeAccess(file)
    return true;
}

function sanityzeForBash(s) {
    return "'"+ s.replace("'","\\'") +"'";
}

function newUUID(){
    return ObjC.unwrap($.NSUUID.UUID.UUIDString);
}

function terminal(c) {
    var app = Application.currentApplication();
    app.includeStandardAdditions = true;
    return app.doShellScript(c);
}

La idea del "truco" es crear un archivo dentro de la carpeta antes de cambiar el ícono para forzar la sincronización de iCloud, luego esperar 1 segundo para eliminar el archivo.

Necesita touchla carpeta para que Finder vuelva a renderizar.
Lo intento, pero cambia intermitentemente el ícono, por primera vez funciona todo el tiempo, pero no si la carpeta tiene un ícono listo. Por fin esto sucede en Catalina.
Me puse a pensar en lo que dices... y encontré el error, el problema es con las carpetas que están dentro de las carpetas de sincronización de iCloud que no sucede en otras carpetas que con el toque es lo único que se necesita.
Código actualizado → Encontré una forma rápida de actualizar el ícono cuando la carpeta está dentro de iCloud.