Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Icono de Itusync: una nota musical saliendo de una carpeta

Itusync

Exporta las listas de reproducción de Music.app a carpetas, una por lista, sin ocupar espacio extra.

Cada archivo exportado es un hard link: apunta a los mismos bytes que el original dentro de la carpeta de Music. Una canción que esté en cinco listas aparece en cinco carpetas y sigue ocupando lo que una. Sobre esta biblioteca, 764 canciones repartidas en 15 carpetas ocupan 0 bytes adicionales.

Es el hermano de Fotosync, que hace lo mismo con los álbumes de Fotos. La diferencia importante es que Itusync no depende de nada: lee la biblioteca con iTunesLibrary, un framework que ya viene con macOS. No hay que instalar Python, ni Homebrew, ni pipx.


Índice


Qué hace y qué no hace

Itusync Itusync no
Lee la biblioteca de Music y crea una carpeta por lista Nunca escribe dentro de la biblioteca de Music
Enlaza cada canción con un hard link (sin duplicar espacio) No convierte, no recomprime, no cambia formatos
Renombra los archivos del destino con esquemas claros No toca las etiquetas ID3/MP4 de nada
Exporta también las listas inteligentes que hayas creado tú No exporta las del sistema («Música», «Videoclips»…)
Actualiza lo ya exportado de forma incremental No vigila en segundo plano: cada cambio exige reejecutar
Con la limpieza activada, borra lo que ya no está en las listas No borra nunca nada de la biblioteca de Music
Funciona sin conexión y sin cuenta de nadie No sincroniza ni sube nada a ningún sitio

No genera archivos .m3u. Cada lista es una carpeta de verdad, con sus archivos dentro. Es lo que entienden los equipos de coche, las radios con USB y cualquier cacharro que lea una tarjeta: un .m3u lo ignoran casi todos.

No es un backup. Los archivos exportados son los mismos bytes que los de la biblioteca: un solo disco, una sola copia. Si el disco falla, se pierden a la vez. Al copiar la carpeta a otro disco los enlaces se convierten en archivos independientes y ahí sí ocupan el tamaño completo.


Requisitos

  • macOS 13 o posterior.
  • Nada más. El framework iTunesLibrary es parte del sistema.
  • Permiso de Multimedia y Apple Música. macOS lo pide la primera vez que abres la app. Si lo deniegas: Ajustes del Sistema → Privacidad y Seguridad → Multimedia y Apple Música. Después hay que cerrar la app por completo y volver a abrirla.
  • El destino debe estar en el mismo volumen que ~/Music: un hard link no puede cruzar sistemas de archivos. Itusync lo comprueba antes de empezar. Si quieres exportar a un USB, desactiva el hard link y acepta copias.
  • Una carpeta de destino de uso exclusivo. No apuntes a ~/Documentos ni a una carpeta con cosas tuyas.

Sobre la firma: build.sh firma la app con el certificado de desarrollador que encuentre en el llavero, y si no hay ninguno, con firma ad-hoc. Merece la pena tener uno: el permiso de Multimedia se concede a una identidad, no a una ruta, así que con firma ad-hoc —que cambia en cada compilación— macOS vuelve a pedirlo cada vez.


Instalación

cd macapp
./build.sh --run

Sale macapp/build/Itusync.app. Se puede arrastrar a Aplicaciones.

Basta con las Command Line Tools de Xcode; no hace falta el Xcode completo ni un proyecto .xcodeproj.

El icono se genera aparte, y solo hace falta si lo cambias:

./make_icon.sh

Dibuja el SVG —la misma placa y la misma carpeta que Fotosync, con la nota de Music en lugar de la flor de Fotos— y lo rasteriza a todos los tamaños del .icns con qlmanage, sips e iconutil, que ya vienen con macOS. build.sh lo copia si existe; si no, la app sale con el icono genérico.


Uso

  1. Elige la carpeta de destino.
  2. Marca las listas que quieras. Sin marcar ninguna se exportan todas, que es el caso normal.
  3. «Ver resultado» enseña el árbol exacto que se va a crear, con los nombres de archivo reales. Se puede desplegar cada carpeta.
  4. «Ensayo» recorre el plan e imprime lo que haría, sin escribir ni borrar nada.
  5. «Exportar» lo hace de verdad, previa confirmación.

La previsualización aquí es exacta, no una estimación: el plan lo arma la propia app antes de tocar el disco. Si un nombre no te convence, cambia el esquema y míralo otra vez —no cuesta nada—.


Cómo queda el resultado

Música-Organizada/
├── .itusync.json                    ← el manifiesto (oculto)
├── Antonio Orozco/
│   ├── Antonio Orozco - Dime por qué.mp3
│   ├── Antonio Orozco - El viaje.mp3
│   ├── Antonio Orozco - El viaje (2).mp3
│   └── …
├── BSO/
├── Chill/
├── La Rosa de los Vientos/
└── Sin lista/                       ← opcional

Sobre esta biblioteca: 15 listas, 764 canciones, 4,37 GB enlazados, 0 bytes de espacio nuevo.

La carpeta «Sin lista» es opcional y viene apagada. Recoge las canciones que no están en ninguna lista —aquí son 720, más que todas las listas juntas—, así que enciéndela solo si quieres el volcado completo de la biblioteca.


Los nombres de archivo

Hay tres esquemas. El nombre importa más aquí que en las fotos, porque dentro de la carpeta de una lista se juntan canciones de álbumes distintos.

Esquema Ejemplo Cuándo
Artista - Título (por omisión) Antonio Orozco - Eres.mp3 Lo normal. Ordena por artista dentro de la carpeta.
Nº de orden + Artista - Título 03 - Antonio Orozco - Eres.mp3 Para un USB de coche: la carpeta ordenada por nombre suena en el orden de la lista.
El nombre original 11 Buscaré y descubriré.mp3 Solo si te hace falta el nombre exacto del archivo de la biblioteca.

Ojo con el tercero: esos nombres vienen numerados por su álbum de origen, así que dentro de la carpeta de una lista el número no significa nada y dos canciones de dos álbumes distintos pueden empezar las dos por 01.

Qué se sanea siempre, con cualquiera de los tres esquemas:

  • / y : pasan a -: son separadores de ruta, el segundo para el Finder.
  • Se quitan los caracteres de control, los puntos y espacios finales —que Windows recorta en silencio— y los puntos iniciales, que esconderían el archivo en el Finder (...Baby One More Time).
  • El nombre se corta a 200 caracteres, lejos del límite del sistema de archivos.

Si a una canción le falta el artista o el título, no queda el guion suelto: se usa lo que haya. Y si dos canciones dan el mismo nombre en la misma carpeta, a la segunda se le añade (2).

Nombres que Windows también sepa abrir

Una casilla aparte, encendida por omisión, que se aplica al nombre de las canciones y también al de las carpetas:

Encendida Apagada
¿Qué pides tú? Andy y Lucas - ¿Qué pides tú.mp3 Andy y Lucas - ¿Qué pides tú?.mp3
LOS NIÑOS DEL CORO | TECHNO REMIX DJ X - LOS NIÑOS DEL CORO - TECHNO REMIX.mp3 DJ X - LOS NIÑOS DEL CORO | TECHNO REMIX.mp3

Sustituye \ | < > * por -, quita ? y convierte las comillas dobles en simples. Conviene saber qué no es el motivo: no es que el USB los rechace. exFAT y FAT32 los admiten y macOS los escribe sin rechistar en volúmenes de los dos formatos. Es que Windows no puede abrir ni renombrar un archivo que los lleve, aunque lo haya creado otro sistema, y muchos reproductores de coche implementan la misma tabla.

Apágala si el destino solo se va a leer desde el Mac y prefieres el nombre exacto. Al cambiarla cambian los nombres, así que la siguiente exportación crea archivos nuevos; si además llevas la limpieza activada, se borran los de la nomenclatura anterior, que es justo lo que se busca.


Mantener la exportación al día

Volver a exportar sobre el mismo destino es incremental y barato. Itusync compara el número de inodo del archivo del destino con el del original: si coinciden, ya es la canción que toca y no hace nada. Sobre esta biblioteca, la segunda pasada da «764 ya estaban» y no escribe ni un byte.

Lo que no se propaga solo es lo que has quitado: si borras una canción de una lista, su archivo sigue en la carpeta del destino hasta que actives la limpieza.

Exportar sin abrir la app

/Applications/Itusync.app/Contents/MacOS/Itusync --export-now

Exporta con la configuración guardada, sin abrir ninguna ventana, y sale con 0 si ha ido bien y 1 si no. Sobre esta biblioteca tarda un segundo y medio.

Está pensado para que otro programa —en concreto Backup SSD, que copia ~/Music/Musica a un disco externo— pueda poner la carpeta al día antes de copiarla. Sin eso, el backup se lleva la exportación de la última vez que alguien abrió Itusync a mano.

Y se le pide a la app, y no a un script, porque el permiso de «Multimedia y Apple Música» se concede a una identidad de firma: lo tiene Itusync. Otro programa que llamara a iTunesLibrary por su cuenta no leería nada.

Qué hace y qué no, en esta modalidad:

No
Exporta todas las listas con las opciones guardadas No hereda la selección de listas de la ventana
Actualiza de forma incremental, como siempre Nunca limpia: no borra ni un archivo del destino
Apunta la fecha en ~/.config/itusync/last-run.json No toca la configuración

Ese archivo es el que contesta a «¿está la carpeta al día?»:

{
  "date": "2026-08-31T14:44:40Z",
  "destination": "/Users/bruno/Music/Musica",
  "ok": true,
  "summary": "1513 ya estaban, 484 actualizados"
}

Se escribe también cuando exportas desde la ventana: lo que importa es cuándo se actualizó la carpeta, no quién dio la orden.


La limpieza: qué borra y qué no

La limpieza de Itusync es más conservadora que la de Fotosync, y por una razón concreta: aquí el exportador es propio y puede llevar la cuenta de lo que escribe.

Cómo decide qué borrar

Cada exportación real deja un manifiesto (.itusync.json) en la raíz del destino con la lista de archivos y carpetas que creó. Al limpiar, Itusync borra la diferencia entre el manifiesto anterior y lo que ha salido de esta ejecución. Nada más.

Eso es distinto de osxphotos --cleanup, que barre el destino y borra todo lo que no salga de la pasada. La consecuencia práctica:

Qué borra

  • Los archivos que Itusync creó en su día y que esta vez no ha vuelto a crear: canciones que quitaste de una lista, listas que borraste, archivos que cambiaron de nombre al cambiar de esquema.
  • Las carpetas de listas que ya no existen, solo si han quedado vacías.

Qué NO borra

  • Cualquier archivo que no conste en el manifiesto. Si dejaste algo tuyo en el destino, Itusync no sabe que existe y no lo toca. Está comprobado: un archivo ajeno metido a mano en una carpeta que se estaba retirando sobrevivió, y la carpeta no se borró por tenerlo dentro.
  • Nada de la biblioteca de Music. Jamás.

Las salvaguardas

  • No se puede limpiar exportando solo algunas listas. Las que dejes fuera están en el manifiesto viejo, no salen de esta ejecución, y se borrarían enteras. La casilla se desactiva sola y explica por qué.
  • No se puede limpiar sin exportación previa. Sin manifiesto no hay lista de la que partir.
  • La limpieza dura una ejecución. Se apaga sola al terminar, para que la siguiente no borre sin que nadie lo pida.
  • El ensayo la simula. Imprime la lista exacta de lo que borraría sin borrar nada.

Importante: no pasa por la Papelera

Los archivos se borran directamente. Como son hard links, borrar uno no afecta a la canción de la biblioteca: los bytes siguen ahí mientras quede algún enlace apuntándolos. Pero si borras algo tuyo del destino, eso sí se pierde.


Qué puede salir mal

El destino está en otro disco. Los hard links no cruzan sistemas de archivos. Itusync lo detecta antes de empezar, incluido el caso traicionero de una ruta /Volumes/Externo/… con el disco desconectado: el ancestro existente pasaría a ser /Volumes, que está en el disco interno, y una comprobación ingenua daría el visto bueno.

El destino dentro de ~/Music. Prohibido, y no por capricho: Music vigila esa carpeta, importaría los enlaces como canciones nuevas y acabarías con la biblioteca duplicada.

Canciones que solo están en la nube. Las de Apple Music que no has descargado no existen como archivo en el Mac, así que no hay nada que enlazar y se quedan fuera. Aquí son 256, y ninguna está en tus listas. Itusync dice cuántas son y en qué listas. La solución es descargarlas en Music y volver a exportar.

Canciones con el archivo perdido. Si moviste o borraste un archivo a mano, Music conserva la ruta en su base de datos aunque no haya nada ahí —es el signo de admiración que enseña—. Itusync comprueba que el archivo exista antes de meterlo en el plan, así que esas se quedan fuera en vez de fallar a mitad de exportación.

Listas inteligentes. Sí se exportan, con las canciones que tengan en el momento del escaneo. Si sus reglas dependen de la fecha o de las reproducciones, el contenido de la carpeta cambiará entre exportaciones y la limpieza irá borrando y añadiendo. Salen marcadas con un icono de engranajes.

Dos listas con el mismo nombre. Music lo permite. La segunda pasa a ser Nombre (2); sin eso, las dos escribirían en la misma carpeta y la limpieza se volvería impredecible.

Cancelar a media exportación. Lo ya enlazado se queda y la siguiente pasada lo dará por hecho. El manifiesto no se actualiza en ese caso: guardar una lista a medias haría que la limpieza siguiente creyera que sobra todo lo que no dio tiempo a escribir.

Copiar la exportación a otro disco. Los hard links se convierten en archivos independientes: ahí sí ocupa el tamaño completo, y multiplicado si tienes canciones en varias listas.

Time Machine y otros backups. Respetan los hard links dentro de un mismo volumen, pero no todas las herramientas de sincronización lo hacen. Comprueba antes de apuntar una a la carpeta exportada, no sea que multiplique el tamaño.

du miente sobre el destino. du -sh sobre la carpeta exportada dice varios gigas. No es espacio nuevo: du suma los archivos que encuentra sin saber que el original vive fuera de lo que está recorriendo. El espacio libre del disco no cambia.


Rendimiento

Medido sobre esta biblioteca (1 751 items, 1 484 canciones en disco, 764 en listas):

Fase Tiempo
Leer la biblioteca entera 0,33 s
Armar el plan (764 archivos, 15 carpetas) 0,00 s
Ensayo 0,03 s
Exportar los 764 enlaces 0,17 s
Reexportar sin cambios 0,10 s

Todo el ciclo está por debajo del segundo, y por motivos que conviene entender:

  • Leer la biblioteca es lo más caro, y aun así son décimas. ITLibrary carga y cachea la biblioteca entera en memoria al construirse; se hace una sola vez, en segundo plano, al abrir la app o al pulsar «Recargar».
  • Armar el plan son unos miles de operaciones de texto sobre datos que ya están en memoria. Por eso la previsualización y los recuentos se recalculan cada vez que cambias una opción, sin caché ni esperas.
  • Enlazar no copia bytes: un hard link solo añade una entrada de directorio. Y reexportar es aún más barato porque casi todo se resuelve comparando números de inodo.

La primera vez es otra historia. Hasta que macOS resuelve el permiso de Multimedia, la primera llamada a ITLibrary puede tardar varios minutos —aquí tardó 174 segundos— y no hay forma de acelerarlo desde la app. Por eso el escaneo va siempre en segundo plano y la ventana sigue viva con su indicador de actividad mientras tanto: si esa llamada se hiciera en el hilo principal, la app parecería colgada durante todo ese rato. No lo está; espera. A partir de la segunda vez son las tres décimas de la tabla.

El registro detallado (una línea por canción) viene desactivado: sobre las listas enteras son más de mil líneas y el resumen sale igual.


Ajustes de la app

⌘, abre dos pestañas:

  • General: apariencia (automática / clara / oscura) y registro detallado.
  • Biblioteca: versión de Music, dónde guarda los archivos, y un botón directo al panel de permisos.

Seguridad

ITLibrary es solo lectura. No existe ninguna llamada en ese framework capaz de modificar la biblioteca de Music, así que nada de lo que haga Itusync puede estropear tus canciones ni tus listas. El único sitio donde se escribe es la carpeta de destino.

La app no va en App Sandbox, a propósito: una app en sandbox no puede escribir en una carpeta arbitraria del usuario ni crear hard links hacia ~/Music.

No hay red. Nada sale del Mac.


Accesibilidad

  • VoiceOver. Cada fila de la lista se lee entera y de una vez («BSO, 43 canciones · lista inteligente») en lugar de deletrear el nombre y el número por separado. Los títulos de sección son encabezados de verdad, así que se salta de uno a otro con VO+H. Al terminar una exportación —que puede durar minutos— el resultado se anuncia solo: la barra de estado está abajo del todo y no recibe el foco, así que sin el anuncio habría que ir a buscarlo.
  • Nada se dice solo con color. Cada aviso y cada error llevan icono y texto; el color es un refuerzo, nunca la señal.
  • Contraste. Los avisos y los errores no usan el naranja y el rojo de sistema, que son colores de relleno: sobre el fondo claro de la ventana dan 2,2:1 y 4:1, por debajo del 4,5:1 que pide la WCAG para texto. Se sustituyen por una pareja de colores dinámicos (Sources/Palette.swift) con cuatro variantes: clara, oscura y las dos de «Aumentar contraste».
  • Reducir transparencia. Con esa opción activada en Ajustes de Accesibilidad, el fondo vibrante de la ventana y el material del registro se vuelven opacos: sobre el escritorio de cualquiera, el contraste del texto no está garantizado.
  • Teclado. ⏎ exporta, Esc cancela el diálogo, y todos los controles entran en el recorrido del tabulador.

La apariencia (automática / clara / oscura) se elige en ⌘, y se aplica a la ventana entera, incluida la de Ajustes.


Idiomas

Español, inglés y francés. La app sigue el idioma del sistema; para forzar uno, Ajustes del Sistema → General → Idioma y región → Apps.

El español es el idioma base: las claves de traducción son las frases en español, así que una cadena sin traducir sale en español en lugar de mostrar un identificador. El diálogo de permiso de Music lo pinta macOS y no la app, así que su texto se traduce aparte, en el InfoPlist.strings de cada .lproj.

Añadir un idioma es copiar un .lproj a macapp/Resources/, traducir la parte derecha y añadir su código a CFBundleLocalizations en build.sh; el resto lo recoge la compilación sola. Los recuentos van en Localizable.stringsdict y no en el código: la regla del plural la aplica el sistema, y un ternario sobre n == 1 solo funciona en un idioma.

macapp/check_strings.py comprueba que las claves no se descuadren, que es el fallo silencioso típico: una clave que no cuadra byte a byte con el literal del código deja la frase en español sin dar ningún error.

138 claves de texto y 14 de plural en 11 archivos.

[en]  138/138 textos, 14/14 plurales
[es]  los literales del código, 14/14 plurales
[fr]  138/138 textos, 14/14 plurales

Licencia

MIT. Ver LICENSE.

About

Exporta las listas de reproduccion de Music.app a carpetas, una por lista, con hard links: no ocupa espacio extra. App nativa en SwiftUI, sin dependencias (iTunesLibrary). Espanol, ingles y frances.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages