Come copiare tutte le cartelle che contengono un file specifico


17

Voglio eseguire il backup solo delle mie cartelle musicali FLAC. I file FLAC potrebbero essere nidificati in questo modo all'interno delle cartelle:

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

Come faccio a copiare e spostare tutte le cartelle di AlbumName con la struttura e il contenuto corrispondenti che contengono da qualche parte all'interno di almeno un file FLAC (suppongo che questo sia sufficiente per dire: la musica è in formato FLAC)

EDIT: i file FLAC potrebbero essere nidificati; così posso avere:

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

E voglio copiare quelle cartelle con tutto il loro contenuto, non solo i file FLAC, e incollarle in un'altra directory.

Quindi, se ho anche

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

e

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

Voglio cp ricorsivamente in un'altra directory AlbumName, AlbumName2 e AlbumName3 ma non AlbumName4

EDIT: Nessuna delle risposte stava davvero facendo quello che voglio, quindi ho finito per usare qualcosa del genere:

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

in pratica elenco tutti i file flac, recupero la cartella principale usando awk, elimino i duplicati e faccio quello che voglio


backup su dove, qual è la tua destinazione?
George Udosen,

Devono essere copiati solo i file flac o intere cartelle che hanno almeno un file flac?
nessuno il

Cartelle @nobody: " Come faccio a copiare e spostare tutte le cartelle di AlbumName con la struttura e il contenuto corrispondenti che contengono da qualche parte all'interno di almeno un file FLAC "
terdon

Risposte:


19

Un'opzione è usare rsync, che copia solo i file flac e conserva la struttura delle directory:

rsync -avzm --include=*/ --include=*.flac --exclude=* albums/ backup/
  • un archivio
  • v verboso
  • z compress durante il trasferimento (potrebbe non essere utile copiare sullo stesso computer)
  • m potare dirs vuoti
  • prima include include tutte le directory
  • la seconda include include i file flac
  • l'ultimo esclude esclude tutti gli altri file

Veramente? Capisco, vuole preservare la struttura delle directory. Dice: "Come faccio a copiare e spostare tutte le cartelle di AlbumName con la struttura e il contenuto corrispondenti ...".
nessuno il

2
Oh, capisco. Non sono sicuro. Devono essere copiati solo i file flac o intere cartelle che hanno almeno un file flac?
nessuno il

La domanda viene modificata e ora spiega in modo più dettagliato cosa vuole Fricadelle. Tenendo conto del fatto che tutto il contenuto deve essere copiato, se esiste un file flac, la mia risposta è errata in quanto copia solo i file flac. Tuttavia, può ancora essere utile per qualche altro scopo.
nessuno il

9

ciao amico mio puoi usare

mkdir newdirectory
cp -r --parents */*.flac newdirectory/

2
Bello mai usato --parentsprima!
George Udosen,

4
Per favore, spiegalo */*.flac! cp -r --parents AlbumName/ newdirectory/Non sarà sufficiente?
George Udosen,

3
Dalla domanda, sembra che i flacs possano o meno essere nelle directory nidificate, quindi consiglierei di abilitare globstar ( shopt -s globstar), quindi utilizzare **/*.flacper il glob. La stella doppia corrisponderà a zero o più directory.
wjandrea,

hai esattamente ragione wjandrea, fammi modificare la mia domanda in modo che tutti capiscano
fricadelle,

5

Belle risposte

Voglio aggiungere un altro modo, puoi anche usare una combinazione di find e cpio

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

Spiegazione:

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.

Esistono 3 modalità cpio:

  • Modalità 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.

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

  • Modalità copia-passaggio: 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.

Qui, stiamo usando la modalità Copia-passa.

  • Opzioni utilizzate nel comando sopra:

trova:

  • -name -> nomefile o usa regex invece di scrivere il nome completo

cpio:

  • '-m, --preserve-change-time' Retain previous file modification times when creating files.
  • '-P, - pass-through' Run in copy-pass mode. see ``Copy-pass mode``.
  • '-d, --make-directories' Create leading directories where needed.'
  • --quiet' Non stampare il numero di blocchi copiati. »

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.

Si può anche usare rsynco scrivere uno script di shell per trovare e copiare file con la struttura di directory.

Per la spiegazione di Rsync, dai un'occhiata alle risposte sopra.


2
Puoi migliorare la tua risposta includendo spiegazioni dei comandi e delle opzioni che suggerisci. - Dalla recensione
J. Starnes il

@dessert sì, giusto. Grazie per il tuo suggerimento perfetto.
bsdboy,

4

Risposta 1: puoi anche usare il findcomando per lo stesso.

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

spiegazione:

mkdircrea una nuova directory. findil comando trova i *.flacfile che si trovano nella AlbumNamecartella. execcomando esegue il cpcomando per ciascuno dei nomi di file che findè tornato.

Risposta 2: È inoltre possibile utilizzare findil comando con xargsoltre

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

Ulteriori informazioni: find , xargs


1
find | xargsinterromperà i nomi dei file con spazi, piuttosto utilizzare find -print0 | xargs -0invece.
dessert,

ho provato con un 1 2.flacfile che ha spazio nel nome del file. Potete per favore fatemi sapere il nome del file su cui find | xargsfallisce?
mf_starboi_8041,

vedi ad esempio qui
dessert

Non lo so, ma sono in grado di copiare il file con un nome lungo che contiene spazio senza utilizzarlofind -print0 | xargs -0
mf_starboi_8041

Prova touch "a space" && find . | xargs ls.
dessert,

0

Ho appena avuto il problema di risolvere lo stesso problema per la mia libreria musicale e l'ho risolto usando il seguente script adattato. Non l'ho progettato completamente con variabili ie, poiché ho intenzione di usarlo solo una volta :).

Lo script sposta ogni directory che contiene i file flac inclusi tutti gli altri file e sottodirectory in una nuova posizione usando rsync. rsync ti consente di riprendere lo script se si interrompe durante il processo.

La mia struttura di biblioteca:

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

Nuova struttura della biblioteca:

library
|-artist
  |- album 1 (mp3)

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

(1) avvia il seguente script di shell nella destinazione SOURCE (sostituisci TARGET con la rispettiva directory di tua scelta - ho appena usato il percorso assoluto)

riga 1: trova tutte le directory contenenti file flac e pipe (|) che nell'ordinamento
riga 2: rimuovi i duplicati con ordinamento e reindirizza l'elenco nel ciclo do
riga 3: per ogni directory esegui la
riga 4: mostra la directory nel processo
riga 5: rsync nella directory di destinazione più rimuovi sorgente e conserva la struttura (-R) nella
riga 6 della posizione di destinazione : rimuovi directory vuota (poiché rsync rimuove solo i file)

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) dopo aver eseguito correttamente lo script in (1) è possibile eseguire il seguente comando nella directory di origine

find . -depth -type d -empty -delete

Questo comando elimina tutte le directory vuote non eliminate all'interno dello script. Vale a dire le directory "Artist", in cui tutte le sottocartelle / album includevano file flac.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.