Acción de carpeta para la limpieza automática del nombre del archivo

Quiero crear una acción de carpeta que limpie los nombres de archivo de mis archivos descargados.

Por ejemplo , Youtube_MyVideofile_(1080p_30fps_H264-128kbit_AAC).mp4 debe eliminarse por "Youtube" "30fps" "128kbit" "AAC" "(" ")" y "_" debe reemplazarse por un "espacio". Entonces el resultado sería MyVideofile 1080p H264.mp4

Sé que podría hacer esto con Automator, pero luego tengo que configurar un elemento de "búsqueda/reemplazo" para cada palabra. Prefiero usar una sola lista de palabras que sería más fácil de mantener, porque tengo muchas fuentes diferentes de las que obtengo archivos de forma regular, por lo que la lista real de palabras que se eliminarán será muy larga y puede ser actualizado de vez en cuando.

¿ Encontré este Automator o AppleScript para eliminar varias cadenas de nombres de archivos? que es similar, pero solo funcionó con carpetas seleccionadas. En cambio, quiero configurarlo para que funcione automáticamente como una acción de carpeta.

Supongo que, por lo tanto, también necesito una lista blanca de extensiones de archivo que el script no tocará, como ".download" para descargas de safari que aún están en progreso.

Proporcione una muestra real de nombres de archivo reales tanto del antes como del después de lo que desea, y edítelo en la pregunta.
¿Qué versión de OS X/macOS estás ejecutando?
Estoy en la última versión de El Capitán.
Bien, acabo de probarlo en OS X 10.11.6 y funciona como se esperaba.

Respuestas (1)

Usando Automator , en macOS Sierra 10.12.5, creé una Acción de carpeta con una sola acción Ejecutar AppleScript , usando el código AppleScript a continuación, y la configuré para que se ejecutara en mi carpeta de Descargas . (También ha sido probado y funciona en OS X 10.8.5 y OSX 10.11.6).

  1. Abra Automator y seleccione Archivo > Nuevo , luego Acción de carpeta .
  2. Agregue una acción Ejecutar AppleScript , reemplazando el código predeterminado con el código a continuación.
  3. Modifique la set theBlackWhiteList to POSIX path of ...línea de código , según sea necesario.
  4. Establezca la Acción de carpeta recibe archivos y carpetas agregados al cuadro de lista Elegir carpeta en su carpeta Descargas .
  5. Antes de guardar la acción de carpeta , cree el archivo de datos de texto sin formato que utilizará esta acción de carpeta .
    • No es absolutamente necesario hacerlo antes, sin embargo, si lo va a guardar en Descargas , primero crearía el archivo.
  6. Guarde el flujo de trabajo de la acción de carpeta de Automator .

Lea los comentarios , incluidos con el código , para saber qué es necesario para usar este código en la Acción de carpeta .

Para probar la Acción de carpeta , abra Terminal y cd Downloads, luego cree el archivo de prueba con,
touch 'Youtube_MyVideofile_(1080p_30fps_H264-128kbit_AAC).mp4'que creará un archivo de longitud cero que será procesado por la Acción de carpeta y se le cambiará el nombre MyVideofile 1080p H264.mp4como se muestra en Descargas en Finder o Terminal con:ls -l My*.mp4

Código AppleScript :

--  #   
--  #   The AppleScript code of this Folder Action requires a data file, which is laid out as follows:
--  #   
--  #   Lines 1 and 3 state what are on lines 2 and 4 respectively. (These lines are just reminders.)
--  #   
--  #   Line 2 must start with a single space character ' ', followed by the comma delimiter ','!
--  #   Line 2 must also not contain an underscore character '_' as it's used as a 'text item delimiter',
--  #   and all of them will be removed and replaced with a single space, as appropriate, in the last
--  #   part of the processing to form the final filename.
--  #   
--  #       This is used as part of the overall logic applied to creating the finished filename, so as to
--  #       only have a single space character between words of the filename, while ensuring the finished
--  #       filename does not start with nor have directly before the filename extension, a space character. 
--  #   
--  #   Line 2 is a list of strings that will be removed from the filename. (The Black List.)
--  #   Line 4 is a list of filename extensions of the file types that will be processed. (The White List.)
--  #   
--  #   Modify lines 2 and 4 as appropriate, while leaving the single space character at the start of line 2,
--  #   and do not include an underscore character in Line 2.
--  #   
--  #   Example contents of the plain text data file:
--  #   

--  #   # Do Not Remove This Line!: The next line contains a comma-delimited list of strings to be removed:
--  #    ,Youtube,30fps,128kbit,-,AAC,(,)
--  #   # Do Not Remove This Line!: The next line contains a comma-delimited list of file extensions to process:
--  #   mp4,mkv,avi,flv,flac

--  #   For the purposes of testing this script, the name of the data file used is 
--  #   "FileNameExtensionBlackWhiteCleanupList.txt", and is in the User's Downloads folder.
--  #   Obviously you can name it whatever you want and place it where appropriate access exists.
--  #   Modify the 'set theBlackWhiteList to POSIX path of ...' line of code, accordingly as necessary.


on run {input, parameters}
    try
        set theBlackWhiteList to POSIX path of (path to downloads folder) & "FileNameExtensionBlackWhiteCleanupList.txt"

        --  #   Make sure the data file exists and set its contents to the target variables.

        tell application "System Events"
            if (exists file theBlackWhiteList) then
                tell current application
                    set theBlackWhiteList to (read theBlackWhiteList)
                    set AppleScript's text item delimiters to {","}
                    set theStringsToRemoveList to text items of paragraph 2 of theBlackWhiteList as list
                    set theFileExtensionsList to text items of paragraph 4 of theBlackWhiteList as list
                    set AppleScript's text item delimiters to {}
                end tell
            else
                tell current application
                    activate
                    display dialog "The required file, " & quoted form of theBlackWhiteList & ", is missing!" & ¬
                        linefeed & linefeed & "Replace the missing file from backup." buttons {"OK"} ¬
                        default button 1 with title "File Not Found" with icon 0 -- (icon stop)
                    return
                end tell
            end if
        end tell

        --  # Process the target file(s) added to the target folder, that have the target filename extensions. 

        tell application "Finder"
            set theFileList to input
            repeat with thisFile in theFileList
                set theFileName to name of thisFile
                set theOriginalFileName to theFileName
                --  #   Get the filename extension of thisfile.
                set AppleScript's text item delimiters to {"."}
                set thisFileExtension to last text item of theFileName as string
                --  #   Only process if thisFileExtension is in theFileExtensionsList. 
                if theFileExtensionsList contains thisFileExtension then
                    repeat with i from 1 to count of theStringsToRemoveList
                        set AppleScript's text item delimiters to item i of theStringsToRemoveList
                        set theTextItems to text items of theFileName
                        set AppleScript's text item delimiters to {"_"}
                        set theFileName to theTextItems as string
                        set AppleScript's text item delimiters to {}
                    end repeat
                    --  #                       
                    --  #   Using the example filename in the OP, 'Youtube_MyVideofile_(1080p_30fps_H264-128kbit_AAC).mp4',
                    --  #   at this point in the processing it would be, '__MyVideofile__1080p___H264_____.mp4', and while one 
                    --  #   probably could continue to use AppleScript 'text items' and 'text item delimiters', nonetheless I can do
                    --  #   it easier using 'sed' to finish getting the final filename. This is also part of the reason I started the
                    --  #   'theStringsToRemoveList' with a single space character and do not allow an underscore character in Line 2.
                    --  #                       
                    tell current application
                        set theFileName to (do shell script "printf " & quoted form of theFileName & " | sed -E -e 's/[_]{2,}/_/g' -e 's/^_//' -e 's/_\\./\\./g' -e 's/_/ /g'")
                    end tell
                    --  #   Only change the filename if it has actually changed by the processing above.
                    --  #   There's no sense in telling Finder to name a file the same name it already is. 
                    if theFileName is not equal to theOriginalFileName then
                        try
                            set the name of thisFile to theFileName
                        end try
                    end if
                    --  #   At this point the final filename, using the example filename, would be 'MyVideofile 1080p H264.mp4'.
                    --  #   This assumes this filename didn't already exist and why the 'do shell script' command is within a 'try'
                    --  #   statement. Additional coding and logic could be applied to increment the filename if it already existed.
                end if
            end repeat
            set AppleScript's text item delimiters to {}
        end tell

    on error eStr number eNum
        set AppleScript's text item delimiters to {}
        display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
        return
    end try
end run

Contenido de ejemplo del archivo de datos de texto sin formato utilizado por la acción de carpeta :

# Do Not Remove This Line!: The next line contains a comma-delimited list of strings to be removed:
 ,Youtube,30fps,128kbit,-,AAC,(,)
# Do Not Remove This Line!: The next line contains a comma-delimited list of file extensions to process:
mp4,mkv,avi,flv,flac

La lógica detrás del proceso de cambio de nombre:

El uso de la variable theStringsToRemoveList , que comienza con un solo carácter de espacio seguido por el delimitador de coma, junto con el carácter de subrayado como text item delimiter, convierte todos los espacios junto con todas las demás cadenas que se eliminarán en guiones bajos durante el AppleScript text itemsy text items delimitersparte del código .

Esto se hace para que sedse pueda usar para reemplazar todos los caracteres de subrayado simultáneos con un solo carácter de subrayado, luego elimine el guión bajo inicial, si existe, seguido de un guión bajo que precede al punto antes de la extensión del nombre de archivo, si existe, y finalmente todo lo que queda solo los caracteres de subrayado se reemplazan con un solo carácter de espacio.

set theFileName to (do shell script "printf " & quoted form of theFileName & " | sed -E -e 's/[_]{2,}/_/g' -e 's/^_//' -e 's/_\\./\\./g' -e 's/_/ /g'")
  • set theFileName to- La variable theFileName contendrá la salida del do shell script comando .
  • do shell script "_command_"- Ejecuta el comando en un shell.
  • printf " & quoted form of theFileName & " |- Imprime el valor de la variable theFileName y |lo canaliza al sed comando .

  • sed -E -e 's/[_]{2,}/_/g' -e 's/^_//' -e 's/_\\./\\./g' -e 's/_/ /g'

  • sed- Editor de flujo.

  • -E- Interprete las expresiones regulares como expresiones regulares extendidas (modernas) en lugar de expresiones regulares básicas (BRE). La página de manual de re_format(7) describe completamente ambos formatos.
  • -e command- Agregar los comandos de edición especificados por el argumento del comando a la lista de comandos.
  • s/[_]{2,}/_/g
    • s- Bandera de patrón de sustitución.
    • [_]{2,}- Coincide con un solo carácter presente en la lista, coincide con el carácter _literalmente (distingue entre mayúsculas y minúsculas).
    • {2,}- Cuantificador: coincidencias entre 2 e ilimitadas veces, tantas veces como sea posible, devolviendo según sea necesario (codicioso).
    • /_/- Reemplaza el patrón coincidente con un solo carácter _literalmente (distingue entre mayúsculas y minúsculas).
    • g- Modificador de bandera de patrón global g, coincide con todas las ocurrencias del patrón (no regresa después de la primera coincidencia).
  • s/^_//
    • ^- Afirma la posición al comienzo de la cadena.
    • _- Coincide con el carácter _literalmente (sensible a mayúsculas y minúsculas).
    • //- Reemplaza el patrón coincidente con literalmente nada.
  • s/_\\./\\./g
    • _- Coincide con el carácter _literalmente (sensible a mayúsculas y minúsculas).
    • \\.- Coincide con el carácter .literalmente (sensible a mayúsculas y minúsculas).
    • /\\./- Reemplaza el patrón coincidente con el carácter .literalmente (se distingue entre mayúsculas y minúsculas).
      • Nota: La doble barra invertida \\es necesaria cuando se usa en un do shell script comando\ ; sin embargo, desde la línea de comando , se usaría una sola barra invertida para convertir el carácter que sigue en un .carácter literal, en este caso.
  • s/_/ /g
    • Reemplaza el carácter _literalmente, con un carácter literalmente (distingue entre mayúsculas y minúsculas).

Tenga en cuenta que la información anterior está abreviada en algunos lugares, sin embargo, debería proporcionar un poco de comprensión de lo que está sucediendo.

En una nota adicional, si también desea garantizar el uso de mayúsculas en cada palabra en el nombre del archivo, reemplace el do shell script comando existente con el siguiente do shell script comando , que tiene un awk comando agregado que recibe el resultado para sedrealizar el uso de mayúsculas. Tenga en cuenta que encontré este awk comando en Internet y probé que funciona, sin embargo, no agregaré una explicación de cómo funciona por falta de tiempo.

set theFileName to (do shell script "printf " & quoted form of theFileName & " | sed -E -e 's/[_]{2,}/_/g' -e 's/^_//' -e 's/_\\./\\./g' -e 's/_/ /g' | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }}1'")

Actualice a la dirección .en el nombre del archivo, según los comentarios.

En el archivo de datos de texto sin formato, en la Línea 2, agregue un .,después del espacio inicial y su delimitador de coma. En otras palabras, el primer elemento de la lista en la línea 2 es un espacio en blanco seguido de un delimitador de coma seguido .de un delimitador de coma y así sucesivamente.

Agregue las siguientes líneas de código después del repeat ciclo que está directamente antes del comentario que comienza con -- # Using the example filename in the OP. ...el cual está arriba del bloque de códigotell current application ... .do shell script

            set AppleScript's text item delimiters to {"_" & thisFileExtension}
            set theTextItems to text items of theFileName
            set AppleScript's text item delimiters to {"_"}
            set theFileName to (theTextItems as string) & "." & thisFileExtension
            set AppleScript's text item delimiters to {}    

Al agregar .,a la línea 2 en el archivo de datos de texto sin formato, todo .el nombre del archivo se reemplaza con el código_ original . Luego, con las líneas adicionales de código anteriores, reemplaza, por ejemplo , con , o y cualquiera que sea la extensión real del nombre de archivo._mp4.mp4.

Ahora, cuando llega al do shell script comando , solo hay .para la extensión del nombre de archivo y todos los guiones bajos se procesan fuera del nombre como deberían.

Obviamente, la forma en que se codifica el código original , los guiones bajos no pueden ser parte del nombre de archivo final, y esta modificación del código original no cambia eso.

Guau. ¡Muchas gracias por tu esfuerzo! ¡Lo intentaré más tarde!
¡Lo probé y su secuencia de comandos funciona absolutamente impecable! También estoy absolutamente impresionado por tu explicación. esto es perfecto para modificar el guión aún más según mis necesidades, ya que podrían cambiar. Solo hay una cosa que lo haría perfecto: si también funcionara con subcarpetas. ¿Puedes ayudar una vez más? ¡¡¡muchas gracias!!!
Usando su descripción, traté de reemplazar "." con espacios alterando su código, tell current application set theFileName to (do shell script "printf " & quoted form of theFileName & " | sed -E -e 's/[_]{2,}/_/g' -e 's/^_//' -e 's/_\\./\\./g' -e 's/_/ /g' -e 's/\\./ /g'") end tellpero también afecta la extensión del archivo y elimina el "." de él y, por lo tanto, el archivo no se reconocerá correctamente. de todos modos para proteger la extensión del proceso de cambio de nombre?
@Maximilian Becker, Este nuevo escenario es exactamente la razón por la que pregunté en el primer comentario a su pregunta " Proporcione una muestra real de los nombres de archivo reales tanto del antes como del después de lo que desea " ¡y solo dio un ejemplo de pseudo nombre de archivo! Si hubiera sabido que habría más .'s para la extensión del nombre de archivo, habría codificado esto de manera diferente. Agregaré una sección al final de la respuesta original para manejar los .'s en el nombre del archivo. No modifique el sed comando , agregaré código para manejar esto antes del do shell script comando .
@Maximilian Becker, agregué una actualización a las direcciones .en los nombres de archivo.