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


17

我只想备份我的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检索了根文件夹,删除了重复项,然后按照我的意愿进行了操作


备份到哪里,您的目的地是什么?
乔治·乌德森

是否仅需要复制flac文件或包含至少一个flac文件的整个文件夹?
没有人

@nobody文件夹:“ 我如何复制和移动所有AlbumName的文件夹以及它们的相应结构和内容,其中至少包含一个FLAC文件中的某个位置
terdon

Answers:


19

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

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

真?我了解,他想保留目录结构。他说:“如何复制和移动所有AlbumName的文件夹及其相应的结构和内容...”。
没有人

2
哦,我懂了。我不确定。是否仅需要复制flac文件或包含至少一个flac文件的整个文件夹?
没有人

该问题已编辑,现在更详细地解释了弗里卡德尔想要什么。考虑到应复制所有内容,如果有flac文件,我的回答是错误的,因为它仅复制flac文件。但是,它可能仍可用于其他目的。
没人

9

嗨,我的朋友,你可以使用

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

2
尼斯从未使用--parents过!
乔治·乌德森

4
请解释一下*/*.flac!会cp -r --parents AlbumName/ newdirectory/不够?
George Udosen '17

3
从问题上来说,听起来好像flac可能位于嵌套目录中,也可能不在嵌套目录中,因此我建议启用globstar(shopt -s globstar),然后将其**/*.flac用于glob。双星将匹配零个或多个目录。
wjandrea

您是完全正确的wjandrea,让我编辑我的问题,以便所有人都知道
fricadelle

5

好答案

我想添加一种方法,您也可以结合使用findcpio

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.

在这里,我们使用复制通过模式。

  • 以上命令中使用的选项:

找:

  • -name-> filename或使用regex代替写全名

cpio:

  • '-m,-保留修改时间' Retain previous file modification times when creating files.
  • '-p,-直通' Run in copy-pass mode. see ``Copy-pass mode``.
  • '-d,--make-directories' 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的说明,请查看以上答案。


2
您可以通过包含命令说明和建议的选项来改善答案。- 评分
J.,斯塔恩斯

@dessert是的,对。谢谢您的完美建议。
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/

更多信息:findxargs


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

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

该脚本使用rsync将包含flac文件的每个目录(包括所有其他文件和子目录)移动到新位置。如果rsync在过程中停止,则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文件和管道(|)的所有目录,进入排序
行2:使用sort和管道删除重复项,并将其列出到do循环中
第3行:对于每个目录,请执行
第4行:在进程
第5行中显示目录: rsync到目标目录并删除源并保留目标位置
第6行中的结构(-R):删除空目录(因为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文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.