Як скопіювати всі папки, які містять певний файл


17

Я хочу створити резервну копію лише моїх папок музики FLAC. Файли FLAC можуть бути такі вкладені у папках:

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

Як скопіювати та перемістити всі папки AlbumName з відповідною структурою та вмістом, які містять десь усередині принаймні один файл FLAC (я вважаю, що цього досить, щоб сказати: музика у форматі FLAC)

EDIT: файли FLAC можуть бути вкладені; тож я можу мати:

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

І я хочу скопіювати ці папки з усім їх вмістом, а не лише файлами FLAC, і вставити в інший каталог.

Тож якщо і в мене

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

і

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

Я хочу перейти рекурсивно в інший каталог AlbumName, AlbumName2 та AlbumName3, але не AlbumName4

EDIT: Жодна з відповідей насправді не робила того, що я хочу, тому я в кінцевому підсумку використовував щось подібне:

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

в основному я перераховую всі файли flac, я отримую кореневу папку за допомогою awk, видаляю дублікати і роблю те, що хочу


резервне копіювання куди, яке ваше призначення?
Джордж Удосен

Чи потрібно копіювати лише файли flac або цілі папки, які мають принаймні один файл flac?
ніхто

папки @nobody: " Як скопіювати та перемістити всі папки AlbumName з відповідною структурою та вмістом, які містять десь усередині принаймні одного файлу FLAC "
тердон

Відповіді:


19

Варіант - використовувати rsync, який копіює лише файли flac та зберігає структуру каталогу:

rsync -avzm --include=*/ --include=*.flac --exclude=* albums/ backup/
  • архів
  • v багатослівний
  • z стискати під час передачі (може бути корисним копіювання на одному комп’ютері)
  • м обрізати порожні дрі
  • Перший включає в себе всі каталоги
  • Другий включає файли flac
  • останнє виключення виключає всі інші файли

Дійсно? Я розумію, він хоче зберегти структуру каталогів. Він каже: "Як скопіювати та перемістити всі папки AlbumName з відповідною структурою та вмістом ...".
ніхто

2
О Я бачу. Я не впевнений. Чи потрібно копіювати лише файли flac або цілі папки, які мають принаймні один файл flac?
ніхто

Питання відредаговано, і тепер воно детальніше пояснює, чого хоче фрикадель. Враховуючи, що весь вміст повинен бути скопійований, якщо є файл flac, моя відповідь неправильна, оскільки він копіює лише файли flac. Однак він все ще може бути корисним для інших цілей.
ніхто

9

привіт мій друг, ти можеш використовувати

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

2
Ніколи --parentsраніше не використовувався !
Джордж Удосен

4
Будь ласка, поясніть це */*.flac! Буде cp -r --parents AlbumName/ newdirectory/не вистачати?
Джордж Удосен

3
З питання, це здається, що flacs можуть бути, а можуть бути і не вкладеними в каталоги, тому я рекомендую включити globstar ( shopt -s globstar), а потім використовувати **/*.flacдля glob. Подвійна зірка буде відповідати нулю або більше каталогів.
wjandrea

Ви точно маєте право, дозвольте мені відредагувати своє запитання, щоб усі зрозуміли
fricadelle

5

Приємні відповіді

Я хочу додати ще один спосіб, ви також можете використовувати комбінацію знаходження і cpio

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

Пояснення:

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.

Існує 3 режиму cpio:

  • Режим копіювання: 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.

  • Режим копіювання: In copy-in mode, cpio copies files out of an archive or lists the archive contents. It reads the archive from the standard input.

  • Режим копіювання: 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.

Тут ми використовуємо режим Copy-pass.

  • Параметри, які використовуються у вищезгаданій команді:

знайти:

  • -name -> ім'я файлу або використовувати regex замість написання повного імені

cpio:

  • '-m, - час збереження-модифікації' Retain previous file modification times when creating files.
  • '-p, - прохідний' Run in copy-pass mode. see ``Copy-pass mode``.
  • '-d, - make-каталоги' Create leading directories where needed.'
  • --quiet' Не друкуйте кількість скопійованих блоків. "

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.

Можна також використовувати rsyncабо написати сценарій оболонки для пошуку та копіювання файлів зі структурою каталогу.

Для пояснення Rsync, будь ласка, подивіться вище на відповіді.


2
Ви можете покращити свою відповідь, включивши пояснення команд та запропонованих варіантів. - З огляду
Дж. Старнес

@ десерт так, правильно. Дякую, за ідеальну пропозицію.
bsdboy

4

Відповідь 1: Ви також можете використовувати findкоманду для того ж.

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

Пояснення:

mkdirстворює новий каталог. findкоманда знаходить *.flacфайли, що знаходяться в AlbumNameпапці. execКоманда виконує cpкоманду до кожного імені файлу, findякий повернувся.

Відповідь 2: Ви також можете використовувати findкоманду з xargsа

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

Більше інформації: знайти , xargs


1
find | xargsрозбивається на назви файлів з пробілами, а скоріше використовувати find -print0 | xargs -0замість них.
десерт

Я намагався з 1 2.flacфайлом, який має простір у імені файлу. Чи можете ви, будь ласка, повідомити мені ім'я файлу, на якому find | xargsне вдалося?
mf_starboi_8041

дивіться, наприклад, тут
десерт

Я не знаю, але я можу скопіювати файл з довгим іменем, який містить простір, що міститься в ньому, без використанняfind -print0 | xargs -0
mf_starboi_8041

Спробуйте touch "a space" && find . | xargs ls.
десерт

0

Просто довелося вирішити ту саму проблему для моєї музичної бібліотеки і вирішив її за допомогою наступного адаптованого сценарію. Я не повністю його інженером, тобто змінними, так як я маю намір використовувати його лише один раз :).

Сценарій переміщує кожен каталог, що містить файли flac, включаючи всі інші файли та підкаталоги, на нове місце за допомогою rsync. rsync дозволяє відновити сценарій, якщо він зупиняється під час процесу.

Структура моєї бібліотеки:

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

Нова структура бібліотеки:

library
|-artist
  |- album 1 (mp3)

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

(1) запустіть наступний скрипт оболонки у пункті ДЖЕРЕЛ (замініть TARGET відповідним каталогом на ваш вибір - я просто використав абсолютний шлях)

рядок 1: знайдіть всі каталоги, що містять файли flac та трубу (|), які входять до
рядка 2 сортування : видаліть дублікати з сортуванням та передайте цей список у
рядок do циклу do : для кожного каталогу do
рядка 4: покажіть каталог у
рядку 5 процесу : rsync в цільовий каталог плюс вилучити джерело та зберегти структуру (-R) у цільовому розташуванні
рядка 6: видалити порожній каталог (як rsync видаляє лише файли)

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) після успішного виконання сценарію в (1) ви можете виконати наступну команду у вихідному каталозі

find . -depth -type d -empty -delete

Ця команда видаляє всі порожні каталоги, не видалені в сценарії. Тобто каталоги «Виконавець», де всі папки / альбоми включали файли flac.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.