Anteponga los nombres de las carpetas al nombre del archivo y aplaste la estructura del archivo

5

Tengo un montón de carpetas con varios nombres, por ejemplo

2013-02   Snow and birds
    PICT0001.jpg
    PICT0002.jpg
2013-06   Bicycle trip
    edited_panorama.jpg
    From phone
        DCIM0001.jpg
        DCIM0002.jpg
        DCIM0003.jpg
    From camera
        DSLR
            PICT0001.raw
            PICT0002.raw
        Compact
            S0000001.jpg           

Como puede ver, la estructura general es un nivel variable de subcarpetas anidadas que contienen imágenes. Lo que quiero hacer es aplanar la estructura, agregando el nombre de cada nivel de subcarpetas al nombre del archivo, de esta manera:

2013-02   Snow and birds_PICT0001.jpg
2013-02   Snow and birds_PICT0002.jpg
2013-06   Bicycle trip_edited_panorama.jpg
2013-06   Bicycle trip_From phone_DCIM0001.jpg
2013-06   Bicycle trip_From phone_DCIM0002.jpg
2013-06   Bicycle trip_From phone_DCIM0003.jpg
2013-06   Bicycle trip_From camera_DSLR_PICT0001.raw
2013-06   Bicycle trip_From camera_DSLR_PICT0002.raw
2013-06   Bicycle trip_From camera_Compact_S0000001.jpg

¿Cómo se puede lograr esto utilizando un script de Terminal o cualquier otro tipo de script? He encontrado algunas soluciones similares, pero todas parecen depender de un nivel fijo de subcarpetas, mientras que la estructura de mi carpeta varía.

Magnus W
fuente

Respuestas:

5

Uno complicado, especialmente si desea mantener todos los espacios, etc. Ejecute lo siguiente en el directorio superior (el que contiene, 2013-02 Snow and birdsetc.):

find . -type f -exec sh -c 'for f do x=${f#./}; echo mv "$x" "${x////_}"; done' {} +

La asignación a xse deshace de la guía ./de find, ${x////_}reemplaza todas las ocurrencias (restantes) de /con _.

Además, he protegido lo real mvcon un echopara que pueda verificar primero si los comandos se ven bien. Vuelva a ejecutar el comando sin echocambiar el nombre / mover los archivos.

nohillside
fuente
Funcionó genial! Sin embargo, perdió 3 archivos de 8300 por alguna razón inexplicable. Afortunadamente, expandí todas las carpetas y subcarpetas después de mover los archivos, ¡solo para asegurarme! Todos los 3 archivos estaban anidados solo a 1 nivel de profundidad y en carpetas donde anteriormente había otros archivos con nombres similares (PICT0001.JPG, etc.).
Magnus W
0

Para los propósitos de este script, tenía todas sus carpetas contenidas en una carpeta llamada "Filez" en mi escritorio. Este script comienza con un cuadro de diálogo "elegir carpeta" para elegir la carpeta que contiene en la que residen las carpetas "Viaje en bicicleta 2013-06" y "Nieve y pájaros 2013-02". Esto devolverá todos los archivos individuales dentro de todas las carpetas y subcarpetas, de las cuales desea que se cambien los nombres.

set mainFolder to choose folder
set posixPathOfMainFolder to POSIX path of mainFolder
tell application "Finder"
    set theNames to files of entire contents of mainFolder as alias list
end tell
set newFileNames to {}
repeat with aFile in theNames
    set text item delimiters to {posixPathOfMainFolder, "/"}
    set aFile to POSIX path of aFile
    set tempName to text items -1 thru 2 of aFile
    set text item delimiters to "_"
    set end of newFileNames to tempName as text
    set text item delimiters to ""
    tell application "Finder"
        set the name of (aFile as POSIX file as alias) to last item of newFileNames as text
    end tell
end repeat
tell application "Finder"
    set theNames to files of entire contents of mainFolder as alias list
    move theNames to mainFolder
    delete folders of mainFolder
end tell

ingrese la descripción de la imagen aquí

wch1zpink
fuente
0

La respuesta de @nohillside anterior es genial en realidad. El único problema es que no tiene en cuenta los archivos con espacios en ellos. Eso hará que algunos de los comandos fallen.

Así que estoy poniendo una respuesta aquí que apoyaría eso también.

Esto solo mostrará echolos mvcomandos:

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; echo "mv ${x// /\ } ${y////-}"; done' {} +

Esto solo enviará echolos mvcomandos directamente a su mesa de trabajo:

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; echo "mv ${x// /\ } ${y////-}"; done' {} + | pbcopy

[Cuidado] Esto ejecutará inmediatamente los mvcomandos para usted:

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; eval "mv ${x// /\ } ${y////-}"; done' {} +
xemacobra
fuente
Ahora tengo curiosidad :-) ¿Qué escenario específico con espacios hace que mi fragmento de código falle?
nohillside
Solo si el nombre del archivo incluye espacios. No se escapa de los caracteres de espacio en el echomodo con una copia directa y pegar, funciona para la mayoría de los archivos, excepto para aquellos que escupen el error que explica el uso de mvusage: mv [-f | -i | -n] [-v] source target
xemacobra
3
Bueno, la idea no es copiar / pegar el resultado, sino eliminar el eco una vez que la salida se ve bien. Pero como siempre hay muchas maneras :-)
nohillside