Jak skopiować wszystkie foldery zawierające określony plik

17

Chcę wykonać kopię zapasową tylko moich folderów muzycznych FLAC. Pliki FLAC można zagnieżdżać w folderach w następujący sposób:

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

Jak skopiować i przenieść wszystkie foldery AlbumName wraz z odpowiednią strukturą i zawartością, które zawierają gdzieś wewnątrz co najmniej jednego pliku FLAC (założę się, że wystarczy powiedzieć: muzyka jest w formacie FLAC)

EDYCJA: Pliki FLAC mogą być zagnieżdżone; więc mogę mieć:

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

I chcę skopiować te foldery z całą ich zawartością, nie tylko plikami FLAC, i wkleić do innego katalogu.

Więc jeśli ja też

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

i

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

Chcę rekurencyjnie cp do innego katalogu AlbumName, AlbumName2 i AlbumName3, ale nie AlbumName4

EDYCJA: Żadna z odpowiedzi tak naprawdę nie działała tak, jak chcę, więc ostatecznie użyłem czegoś takiego:

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

w zasadzie wymieniam wszystkie pliki flac, odzyskuję folder główny za pomocą awk, usuwam duplikaty i robię, co chcę

fricadelle
źródło
kopia zapasowa gdzie, gdzie jest twój cel?
George Udosen
Czy należy kopiować tylko pliki flac, czy całe foldery, które zawierają co najmniej jeden plik flac?
nikt
@nobody foldery: „ Jak skopiować i przenieść wszystkie foldery AlbumName wraz z odpowiadającą im strukturą i zawartością, które zawierają co najmniej jeden plik FLAC
terdon

Odpowiedzi:

19

Opcją jest użycie rsync, który kopiuje tylko pliki flac i zachowuje strukturę katalogów:

rsync -avzm --include=*/ --include=*.flac --exclude=* albums/ backup/
  • archiwum
  • v pełne
  • z kompresuj podczas przesyłania (kopiowanie na tym samym komputerze może nie być przydatne)
  • m przycinaj puste katalogi
  • pierwszy obejmuje wszystkie katalogi
  • drugi obejmuje pliki flac
  • ostatnie wykluczenie wyklucza wszystkie inne pliki
nikt
źródło
Naprawdę? Rozumiem, chce zachować strukturę katalogów. Mówi: „Jak skopiować i przenieść wszystkie foldery AlbumName wraz z odpowiednią strukturą i zawartością ...”.
nikt
2
Rozumiem. Nie jestem pewien. Czy należy kopiować tylko pliki flac, czy całe foldery, które zawierają co najmniej jeden plik flac?
nikt
Pytanie zostało zredagowane, a teraz wyjaśnia bardziej szczegółowo, czego chce fricadelle. Biorąc pod uwagę, że cała treść zostanie skopiowana, jeśli istnieje plik flac, moja odpowiedź jest błędna, ponieważ kopiuje tylko pliki flac. Jednak może być nadal przydatny do innych celów.
nikt
9

cześć mój przyjacielu możesz użyć

mkdir newdirectory
cp -r --parents */*.flac newdirectory/
amir.m ghazanfari
źródło
2
Nicea nigdy --parentswcześniej nie używana !
George Udosen
4
Wyjaśnij to */*.flac! Czy cp -r --parents AlbumName/ newdirectory/nie wystarczy?
George Udosen
3
Z pytania wynika, że ​​flacs może, ale nie musi, znajdować się w zagnieżdżonych katalogach, więc polecam włączyć globstar ( shopt -s globstar), a następnie użyć **/*.flacdla glob. Podwójna gwiazda będzie pasować do zera lub więcej katalogów.
wjandrea
masz rację wjandrea, pozwól mi edytować moje pytanie, aby wszyscy rozumieli
fricadelle
5

Niezłe odpowiedzi

Chcę dodać jeszcze jeden sposób, możesz także użyć kombinacji find i cpio

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

Wyjaśnienie:

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.

Istnieją 3 tryby CPIO:

  • Tryb kopiowania: 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.

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

  • Tryb kopiowania i przekazywania: 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.

W tym przypadku korzystamy z trybu Copy-pass.

  • Opcje użyte w powyższym poleceniu:

odnaleźć:

  • -nazwa -> nazwa_pliku lub użyj wyrażenia regularnego zamiast pisać pełne imię i nazwisko

CPIO:

  • „-m, --preserve-modyfikacja-czas” Retain previous file modification times when creating files.
  • „-p, - pass-through” Run in copy-pass mode. see ``Copy-pass mode``.
  • „-d, --make-katalogi” Create leading directories where needed.'
  • --quiet' Nie drukuj liczby skopiowanych bloków. ”

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.

Można również użyć rsynclub napisać skrypt powłoki, aby znaleźć i skopiować pliki o strukturze katalogów.

Aby uzyskać wyjaśnienie Rsync, spójrz na powyższe odpowiedzi.

bsdboy
źródło
2
Możesz poprawić swoją odpowiedź, włączając objaśnienia poleceń i sugerowane opcje. - Z recenzji
J. Starnes,
@dessert tak, racja. Dziękuję za idealną sugestię.
bsdboy,
4

Odpowiedź 1: Możesz także użyć findpolecenia do tego samego.

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

Wyjaśnienie:

mkdirtworzy nowy katalog. findpolecenie wyszukuje *.flacpliki znajdujące się w AlbumNamefolderze. execpolecenie wykonuje cppolecenie dla każdej findzwróconej nazwy pliku .

Odpowiedź 2: Można również użyć findpolecenia z xargstak dobrze

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

Więcej informacji: znajdź , xargs

mf_starboi_8041
źródło
1
find | xargszepsuje nazwy plików spacjami, zamiast find -print0 | xargs -0tego użyj .
deser
próbowałem z 1 2.flacplikiem, który ma miejsce w nazwie pliku. Czy możesz podać nazwę pliku, w przypadku którego find | xargswystąpił błąd?
mf_starboi_8041
patrz np. tutaj
deser
Nie wiem, ale jestem w stanie skopiować plik o długiej nazwie, który zawiera w sobie miejsce bez użyciafind -print0 | xargs -0
mf_starboi_8041,
Spróbować touch "a space" && find . | xargs ls.
deser
0

Właśnie musiałem rozwiązać ten sam problem dla mojej biblioteki muzycznej i rozwiązać go za pomocą następującego dostosowanego skryptu. Nie zaprojektowałem go w pełni przy użyciu np. Zmiennych, ponieważ zamierzam go użyć tylko raz :).

Skrypt przenosi każdy katalog zawierający pliki flac, w tym wszystkie inne pliki i podkatalogi, do nowej lokalizacji za pomocą rsync. rsync pozwala wznowić skrypt, jeśli zatrzyma się podczas procesu.

Moja struktura biblioteki:

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

Nowa struktura biblioteki:

library
|-artist
  |- album 1 (mp3)

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

(1) uruchom następujący skrypt powłoki w miejscu docelowym SOURCE (zamień TARGET na odpowiedni katalog do wyboru - właśnie użyłem ścieżki bezwzględnej)

wiersz 1: znajdź wszystkie katalogi zawierające pliki flac i potok (|), które sortują w
wierszu 2: usuń duplikaty za pomocą sortowania i potoku, które wyświetlają się w
wierszu 3 do pętli : dla każdego katalogu wykonaj
wiersz 4: pokaż katalog w
wierszu procesu 5: rsync do katalogu docelowego plus usuń źródło i zachowaj strukturę (-R) w
wierszu 6 lokalizacji docelowej : usuń pusty katalog (ponieważ rsync usuwa tylko pliki)

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) po pomyślnym wykonaniu skryptu w (1) możesz wykonać następującą komendę w katalogu źródłowym

find . -depth -type d -empty -delete

To polecenie usuwa wszystkie puste katalogi, które nie zostały usunięte w skrypcie. Tzn. Katalogi „Artist”, w których wszystkie podfoldery / albumy zawierały pliki flac.

wundabua
źródło