Cambiar la estructura de carpetas basada en fecha creada por AppleScript

1

Tengo un AppleScript que se ha escrito y funciona como tal, pero necesito cambiar la forma en que crea la estructura de carpetas. El script hace lo siguiente:

  • Se seleccionó la carpeta que contiene archivos (en mi caso, serán fotos).
  • Luego mirará las fotos creadas en la fecha.
  • Cree un YYYY (la carpeta del año, si aún no se ha creado).
  • Cree un MM (carpeta de mes si no está creada).
  • Crea una DD (carpeta de día si no está creada).
  • Luego moverá la foto a esta carpeta y la repetirá para la siguiente foto y la repetirá hasta que se complete.

La estructura de carpetas actual se crea de la siguiente manera:

2018 "YYYY"
├── 2018-01 "MM"
├── 2018-02

Esto es genial y funciona según lo diseñado, pero he cambiado de opinión sobre cómo me gustaría que se vieran las carpetas. Me gustaría la siguiente estructura (que es casi la misma, solo una estructura de nomenclatura diferente:

2018
├── 001 January
│   ├── 20180101
│   └── 20180102
├── 002 February
│   ├── 20180201
│   └── 20180202
└── 003 March
    ├── 20180301
    └── 20180302

Ahora he intentado averiguar dónde genera el script esto, pero he fallado, por lo que ahora me dirijo a este gran lugar en busca de ayuda.

on run
    SortFiles(POSIX path of (choose folder))
end run

on open (DroppedFolder)
    set DroppedFolder to POSIX path of DroppedFolder
    if text (length of text of DroppedFolder) of DroppedFolder is not "/" then quit
    SortFiles(DroppedFolder)
end open

on SortFiles(SortFolder)
    set AppleScript's text item delimiters to return
    set SortFolderContents to the text items of (do shell script "find '" & SortFolder & "' -type f")
    set FolderMakeList to {}
    repeat with ThisItem in SortFolderContents
        set ThisFile to ThisItem as string
        if ThisFile does not contain "/." then
            tell application "Finder"
                set DateString to text 1 thru 7 of ((creation date of ((POSIX file ThisFile) as alias)) as «class isot» as string)
                set ThisFilesFolder to SortFolder & text 1 thru 4 of DateString & "/"
                set ThisFilesSubfolder to ThisFilesFolder & text 1 thru 7 of DateString & "/"
            end tell
            if ThisFilesFolder is not in FolderMakeList then
                try
                    do shell script ("mkdir '" & ThisFilesFolder & "'")
                end try
                set FolderMakeList to FolderMakeList & ThisFilesFolder
            end if
            if ThisFilesSubfolder is not in FolderMakeList then
                try
                    do shell script ("mkdir '" & ThisFilesSubfolder & "'")
                end try
                set FolderMakeList to FolderMakeList & ThisFilesSubfolder
            end if
            try
                do shell script ("mv '" & ThisFile & "' '" & ThisFilesSubfolder & "'")
            end try
        end if
    end repeat
    return FolderMakeList
end SortFiles
    
pregunta Adam Mann Pro 21.12.2018 - 14:46

2 respuestas

3

La parte de su script que nombra las carpetas es esta línea:

set ThisFilesFolder to SortFolder & (do shell script ("date -r " & ThisFilesEpoch & " \"+%b-%Y\"")) & "/"

Sin embargo, en mi breve prueba de su script, no parece que se cree la estructura de carpetas que describió, lo que no me sorprende, dado que el comando de shell se utilizó para generar la cadena de fecha desde la cual nombre de la carpeta es esta:

date -r %time% "+%b-%Y"

donde se inserta %time% por medio de la variable ThisFilesEpoch y representa el número de segundos desde la Época (1 de enero de 1970) en que se creó el archivo (o, mejor dicho, su inodo). Esta función de shell, date , toma este valor (un entero grande), que entiende como un valor en "tiempo de Unix", y lo reformatea utilizando una representación canónica según los tokens %b (que representa un abreviatura de tres letras para el mes) y %Y (que representa un número de cuatro dígitos para el año).

Entonces, por ejemplo:

date -r 1534615274 "+%b-%Y"

devuelve:

Aug-2018

a la que se movieron los archivos de agosto de 2018 que tenía en la carpeta elegida. No creó carpetas separadas para el día del mes, ni siquiera carpetas separadas para un año; Sólo carpetas "month-year" . Por lo tanto, estoy confundido de que parezca que ha descrito una secuencia de comandos completamente diferente.

El script también tiene una serie de cualidades que me molestan mucho, como:

  1. Su uso perezoso de try ... end try ;

  2. La inserción de comillas simples literales que rodean una variable que se utiliza como parte de una cadena, por ejemplo,

    do shell script "find '" & SortFolder & "' -type f" 
    

    en lugar de

    do shell script "find " & quoted form of SortFolder & " -type f" 
    
  3. Esta formulación extraña:

    if text (length of text of DroppedFolder) of DroppedFolder is not "/" then...
    

    que podría escribirse como

    if text -1 of DroppedFolder is not "/" then...
    

    o como

    if the last character of DroppedFolder is not "/" then...
    

    o incluso

    if DroppedFolder does not end with "/" then...
    
  4. Y el uso repetido de do shell script , lo cual está bien como una herramienta de comando para ser invocado de manera reflexiva cuando sea necesario, pero cuando rellena el script tan densamente como este. se pregunta por qué el script no solo se escribió como un script shell / bash para empezar. También es muy costoso en términos de gastos generales crear y destruir procesos de shell uno tras otro como lo hace este script.

Dados estos inconvenientes estilísticos y funcionales, más la confusión sobre lo que se supone que debe hacer el script actualmente y lo que realmente parece hacer, sentí que justificaba una reescritura:

use Finder : application "Finder"
property rootdir : missing value

# The default run handler when run within Script Editor
on run
    using terms from scripting additions
        set root to choose folder
    end using terms from
    set rootdir to Finder's folder root                         -- '
    sortFiles()
end run

# Processes items dropped onto the applet.  The handler expects one or more 
# file references in the form of an alias list, and will process each item in 
# the list in turn.  If an item is not a folder reference, it is ignored.
# For the rest, the contents of each folder is reorganised.
on open droppedItems as list
    repeat with drop in droppedItems
        set rootdir to Finder's item drop
        if rootdir's class = folder then sortFiles()
    end repeat
end open

# Obtains every file in the root directory and all subfolders, moving them
# to new folders nested within the root directory and organised by year, month,
# and date of each file's creation
to sortFiles()
    repeat with f in the list of fileitems()
        set [yyyy, m, dd] to [year, month, day] of (get ¬
            the creation date of Finder's file f)               -- '

        set mmm to text -3 thru -1 of ("00" & (m * 1)) -- e.g. "008"
        set mm to text -2 thru -1 of mmm -- e.g. "08"
        set dd to text -2 thru -1 of ("0" & dd) -- e.g. "01"

        (my newFolderNamed:yyyy inFolder:rootdir)
        (my newFolderNamed:[mmm, space, m] inFolder:result)

        move Finder's file f to my newFolderNamed:[yyyy, mm, dd] ¬
            inFolder:result                                     -- '
    end repeat
end sortFiles

# A handler to house a script object that enumerates the contents of a 
# directory to its full depth
on fileitems()
    script
        property list : every document file in the ¬
            entire contents of the rootdir ¬
            as alias list
    end script
end fileitems

# Creates a new folder with the supplied name in the specified directory, 
# checking first to see whether a folder with that name already exists.  
# In either case, a Finder reference to the folder is returned.
to newFolderNamed:(dirname as text) inFolder:dir
    local dirname, dir

    tell (a reference to folder dirname in the dir) ¬
        to if it exists then return it

    make new folder at the dir with properties {name:dirname}
end newFolderNamed:inFolder:

Le insto a que pruebe esta secuencia de comandos inicialmente en un directorio de prueba que contenga archivos de muestra. De hecho, el peor de los casos es el mismo que con su script actual, que es la situación en la que elige el directorio equivocado por error. Suponiendo que se seleccione el directorio correcto, el peor de los casos es que los archivos no se mueven, por lo que generalmente es un script muy seguro.

También reescribí el controlador open , para (con suerte) permitirle atender múltiples elementos que se colocan en el applet. Esto significa que podría, por ejemplo, colocar dos carpetas en él y tener el contenido de ambas carpetas reestructurado. Sin embargo, no he probado esto. Una vez más, el peor de los casos aquí es que no hace nada, lo que ocurrirá si me equivoco sobre qué tipo de referencia de archivo se pasa al controlador open (supongo que será alias objetos) .

    
respondido por el CJK 22.12.2018 - 10:37
0

Cambia el% b,% Y etc.

Aquí hay una clave: enlace

    
respondido por el Matt Sephton 21.12.2018 - 17:23

Lea otras preguntas en las etiquetas