如何复制包含特定文件的所有文件夹

如何复制包含特定文件的所有文件夹

我只想备份我的 FLAC 音乐文件夹。FLAC 文件可以像这样嵌套在文件夹中:

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

如何复制和移动所有 AlbumName 的文件夹及其相应的结构和内容,其中包含至少一个 FLAC 文件(我假设这足以说明:音乐是 FLAC 格式)

编辑: 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

我想递归地 cp 到另一个目录 AlbumName、AlbumName2 和 AlbumName3,但不是 AlbumName4

编辑: 没有一个答案真正满足我的要求,所以我最终使用了类似这样的方法:

 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 检索根文件夹,我删除了重复项,然后我做了我想做的事情

答案1

一种选择是使用 rsync,它只复制 flac 文件并保留目录结构:

rsync -avzm --include=*/ --include=*.flac --exclude=* albums/ backup/
  • 档案
  • 非常详细
  • z 传输过程中压缩(在同一台计算机上复制可能无用)
  • m 删除空目录
  • 首先包含所有目录
  • 第二个包含 flac 文件
  • 最后一个排除排除所有其他文件

答案2

嗨我的朋友你可以使用

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

答案3

很好的答案

我想再补充一种方法,你也可以使用以下组合寻找太平洋保险协会

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.

cpio 有 3 种模式:

  • 复印模式: 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 -> 文件名或使用正则表达式代替全名

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或编写 shell 脚本来查找和复制具有目录结构的文件。

有关 Rsync 的解释,请查看以上答案。

答案4

刚刚为我的音乐库解决了同样的问题,并使用以下改编的脚本解决了它。我没有完全用 ie 变量来设计它,因为我只打算使用它一次 :)。

该脚本使用 rsync 将每个包含 flac 文件的目录(包括所有其他文件和子目录)移动到新位置。如果脚本在过程中停止,rsync 允许您恢复该脚本。

我的图书馆结构:

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

新的库结构:

library
|-artist
  |- album 1 (mp3)

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

(1)在 SOURCE 目标中启动以下 shell 脚本(将 TARGET 替换为您选择的相应目录 - 我只使用了绝对路径)

第 1 行:查找所有包含 flac 文件的目录,并通过管道 (|) 将其放入 sort 行
第 2 行:使用 sort 删除重复项,并将该列表放入 do 循环
第 3 行:对每个目录执行
第 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

此命令删除所有空的脚本中未删除的目录。例如“Artist”目录,其中所有子文件夹/专辑都包含 flac 文件。

相关内容