Cómo copiar todas las carpetas que contienen un archivo específico

17

Quiero hacer una copia de seguridad solo de mis carpetas de música FLAC. Los archivos FLAC se pueden anidar así dentro de las carpetas:

AlbumName/
├── Files/
│   ├── someSong01.flac
│   ├── someSong02.flac
├── Covers/
│   ├── someCover01.jpg
│   └── someCover02.jpg

¿Cómo copio y muevo todas las carpetas de AlbumName con su estructura y contenido correspondientes que contienen en algún lugar dentro de al menos un archivo FLAC (supongo que esto es suficiente para decir: la música está en formato FLAC)

EDITAR: los archivos FLAC podrían estar anidados; para que pueda tener:

AlbumName2/
├── someSong01.flac
├── someSong02.flac
├── Covers/
│   ├── someCover01.jpg
|   └── someCover02.jpg

Y quiero copiar esas carpetas con todo su contenido, no solo los archivos FLAC, y pegarlas en otro directorio.

Entonces si yo también tengo

AlbumName3/
├── someSong01.mp3
├── someSong02.mp3
├── Covers/
│   ├── someCover01.jpg
|   └── someHiddenSong.flac

y

AlbumName4/
├── Files/
│   ├── someSong01.mp3
│   ├── someSong02.mp3
├── Covers/
│   ├── someCover01.jpg
│   └── someCover02.jpg

Quiero cp recursivamente a otro directorio AlbumName, AlbumName2 y AlbumName3 pero no AlbumName4

EDITAR: Ninguna de las respuestas estaba realmente haciendo lo que quería, así que terminé usando algo así:

 find -mindepth 2 -name '*.flac' -exec dirname {} \; | awk -F "/" '{print $2}' | sort -u | while read -r dirname; do cp -r "$dirname" "backup/"; done

básicamente enumero todos los archivos flac, recupero la carpeta raíz usando awk, elimino los duplicados y hago lo que quiero

fricadelle
fuente
copia de seguridad a dónde, ¿cuál es su destino?
George Udosen
¿Solo se deben copiar archivos flac o carpetas completas que tengan al menos un archivo flac?
nadie
carpetas @nobody: " ¿Cómo puedo copiar y mover todos ALBUMNAME de carpetas con su correspondiente estructura y el contenido que contienen algún lugar dentro de al menos un archivo FLAC "
terdon

Respuestas:

19

Una opción es usar rsync, que copia solo archivos flac y conserva la estructura de directorios:

rsync -avzm --include=*/ --include=*.flac --exclude=* albums/ backup/
  • un archivo
  • v detallado
  • z comprimir durante la transferencia (puede que no sea útil copiar en la misma computadora)
  • m podar directorios vacíos
  • primero incluye todos los directorios
  • la segunda inclusión incluye archivos flac
  • la última exclusión excluye todos los demás archivos
nadie
fuente
De Verdad? Entiendo, él quiere preservar la estructura del directorio. Él dice: "¿Cómo copio y muevo todas las carpetas de AlbumName con su estructura y contenido correspondiente ...".
nadie
2
Oh ya veo. No estoy seguro. ¿Solo se deben copiar archivos flac o carpetas completas que tengan al menos un archivo flac?
nadie
La pregunta se edita y ahora explica con más detalle lo que quiere fricadelle. Teniendo en cuenta que todo el contenido se copiará, si hay un archivo flac, mi respuesta es incorrecta, ya que solo copia archivos flac. Sin embargo, aún puede ser útil para algún otro propósito.
nadie
9

hola mi amigo puedes usar

mkdir newdirectory
cp -r --parents */*.flac newdirectory/
amir.m ghazanfari
fuente
2
Bonito nunca usado --parentsantes!
George Udosen
44
Por favor explique esto */*.flac! cp -r --parents AlbumName/ newdirectory/No será suficiente?
George Udosen
3
A partir de la pregunta, parece que los flacs pueden o no estar en directorios anidados, por lo que recomendaría habilitar globstar ( shopt -s globstar) y luego usarlo **/*.flacpara el glob. La estrella doble coincidirá con cero o más directorios.
wjandrea
tienes toda la razón wjandrea, déjame editar mi pregunta para que todos entiendan
fricadelle
5

Buenas respuestas

Quiero agregar una forma más, también puedes usar una combinación de find y cpio

find . -name "*.flac" -print0|cpio --null -pdm destination/

Explicación:

GNU find searches the directory tree rooted at each given file name by evaluating the given expression from left to right, according to the rules of precedence (see Operators), until the outcome is known (the left-hand side is false for AND operations, true for OR), at which point find moves on to the next file name.

GNU cpio is a tool for creating and extracting archives, or copying files from one place to another. It handles a number of cpio formats as well as reading and writing tar files.

Hay 3 modos cpio:

  • Modo de copia: In copy-out mode, cpio copies files into an archive. It reads a list of filenames, one per line, on the standard input, and writes the archive onto the standard output.

  • Modo de copia: In copy-in mode, cpio copies files out of an archive or lists the archive contents. It reads the archive from the standard input.

  • Modo copia-pase: In copy-pass mode, cpio copies files from one directory tree to another, combining the copy-out and copy-in steps without actually using an archive. It reads the list of files to copy from the standard input; the directory into which it will copy them is given as a non-option argument.

Aquí, estamos usando el modo Copia-pase.

  • Opciones utilizadas en el comando anterior:

encontrar:

  • -name -> filename o usa regex en lugar de escribir el nombre completo

cpio:

  • '-m, - preservar-modificación-tiempo' Retain previous file modification times when creating files.
  • '-p, - paso' Run in copy-pass mode. see ``Copy-pass mode``.
  • '-d, --make-directorios' Create leading directories where needed.'
  • --quiet' No imprima el número de bloques copiados.`

New options are the "-print0" available with GNU find, combined with the "--null" option of cpio. These two options act together to send file names between find and cpio, even if special characters are embedded in the file names.

También se puede usar rsynco escribir un script de shell para buscar y copiar archivos con la estructura de directorios.

Para obtener una explicación de Rsync, consulte las respuestas anteriores.

bsdboy
fuente
2
Puede mejorar su respuesta al incluir explicaciones de los comandos y las opciones que sugiere. - De la opinión
J. Starnes
@dessert sí, claro. Gracias por tu sugerencia perfecta.
bsdboy
4

Respuesta 1: También puede usar el findcomando para lo mismo.

mkdir newDir && find AlbumName/ -iname "*.flac" -exec cp --parents "{}" newDir/ \;

Explicacion:

mkdircrea un nuevo directorio findEl comando encuentra los *.flacarchivos ubicados en la AlbumNamecarpeta. execEl comando ejecuta el cpcomando para cada uno de los nombres de archivo que findha regresado.

Respuesta 2: También puede utilizar findcomandos con xargsasí

mkdir newDir && find AlbumName/ -iname "*.flac" | xargs -I{} cp --parents {} newDir/

Más información: buscar , xargs

mf_starboi_8041
fuente
1
find | xargsse romperá en los nombres de archivo con espacios, más bien use find -print0 | xargs -0en su lugar.
postre
Intenté con un 1 2.flacarchivo que tiene espacio en el nombre del archivo. ¿Me puede decir el nombre del archivo en el que find | xargsfalla?
mf_starboi_8041
ver, por ejemplo, aquí
postre
No lo sé, pero puedo copiar un archivo con un nombre largo que contiene espacio sin usarlofind -print0 | xargs -0
mf_starboi_8041
Tratar touch "a space" && find . | xargs ls.
postre
0

Solo tuve que resolver el mismo problema para mi biblioteca de música y lo resolví usando el siguiente script adaptado. No lo diseñé completamente con variables, es decir, solo tengo la intención de usarlo una vez :).

El script mueve todos los directorios que contienen archivos flac, incluidos todos los demás archivos y subdirectorios, a una nueva ubicación mediante rsync. rsync le permite reanudar el script si se detiene durante el proceso.

La estructura de mi biblioteca:

library
|-artist
  |- album 1 (mp3)
  |- album 2 (flac)

Nueva estructura de biblioteca:

library
|-artist
  |- album 1 (mp3)

library-lossless
|-artist
  |- album 2 (flac)

(1) inicie el siguiente script de shell en el destino SOURCE (reemplace TARGET con el directorio respectivo de su elección; acabo de utilizar la ruta absoluta)

fila 1: busque todos los directorios que contengan archivos flac y canalización (|) que en la clasificación
fila 2: elimine los duplicados con clasificación y canalización que figuran en el ciclo do
fila 3: para cada directorio
fila 4: muestre el directorio en el proceso
fila 5: rsync al directorio de destino más eliminar la fuente y preservar la estructura (-R) en la
fila de ubicación de destino 6: eliminar el directorio vacío (como rsync solo elimina los archivos)

find . -type f -name \*.flac -printf "%h\n" | 
sort -u | 
while read -r dirname; do
    echo $dirname
    rsync -azvm -R --remove-source-files "${dirname}" TARGET
    find "${dirname}" -type d -delete
done

(2) después de ejecutar con éxito el script en (1), puede ejecutar el siguiente comando en el directorio de origen

find . -depth -type d -empty -delete

Este comando elimina todos los directorios vacíos no eliminados dentro del script. Es decir, directorios "Artist", donde todas las subcarpetas / álbumes incluían archivos flac.

wundabua
fuente