rsync:递归同步所有文件,同时忽略目录结构

时间:2013-02-02 10:41:05

标签: bash rsync

我正在尝试创建一个bash脚本,用于将音乐从桌面同步到移动设备。桌面是源。

有没有办法让rsync递归同步文件但忽略目录结构?如果文件已从桌面删除,我也希望它也可以在设备上删除。

我桌面上的目录结构是这样的。

    Artist1/
        Artist1/art1_track1.mp3
        Artist1/art1_track2.mp3
        Artist1/art1_track3.mp3
    Artist2/
        Artist2/art2_track1.mp3
        Artist2/art2_track2.mp3
        Artist2/art2_track3.mp3
    ...

我想要在设备上的目录结构是:

    Music/
        art1_track1.mp3
        art1_track2.mp3
        art1_track3.mp3
        art2_track1.mp3
        art2_track2.mp3
        art2_track3.mp3
    ...

4 个答案:

答案 0 :(得分:13)

简单地:

rsync -a --delete --include=*.mp3 --exclude=* \
    pathToSongs/Theme*/Artist*/. destuser@desthost:Music/.
如果您的路径层次结构具有固定数量的级别,

将完成此任务。

警告:如果两个歌曲文件的名称完全相同,则在同一目标目录中,您的备份将错过其中一个!

如果没有其他问题,并严格按照忽略目录结构进行回答,您可以使用shopt -s globstar功能:

shopt -s globstar
rsync -a --delete --include=*.mp3 --exclude=* \
    pathToSongsRoot/**/. destuser@desthost:Music/.

完全没有必要分叉到find命令。

递归同步所有文件,同时忽略目录结构

要严格回答问题,不得限于扩展名:

shopt -s globstar
rsync -d --delete sourceRoot/**/. destuser@desthost:destRoot/.

这样,目录也将被复制,但没有内容。所有文件目录都将存储在destRoot/的同一级别。

警告:如果在defferents目录中存在一些具有相同名称的不同文件,它们只会在目标上被覆盖,在rsync之前,最终只能随机存储一个。

答案 1 :(得分:7)

可能这是最近的选项,但我看到--no-relative文档中提到的选项--files-from,效果很好。

find SourceDir -name \*.mp3 | rsync -av --files-from - --no-relative . DestinationDir/

答案 2 :(得分:1)

你的问题的答案:不,rsync不能单独做到这一点。但是在其他工具的帮助下,我们可以到达那里......经过几次尝试,我想出了这个:

rsync -d --delete $(find . -type d|while read d ; do echo $d/ ; done) /targetDirectory && rmdir /targetDirectory/* 2>&-

难点在于:要在目标位置删除文件,您需要:

  1. 指定目录作为rsync的源(如果源是文件列表,则不会删除。)
  2. 立即为它提供完整的源列表(循环中的rsync将仅为目标提供最后一个目录的内容。)
  3. 使用斜杠结束目录名称(否则会在目标目录中创建目录)
  4. 因此命令替换($( )附带的内容)执行此操作:它找到所有目录并在目录名称的末尾添加斜杠(/)。现在,rsync会看到一个源目录列表,所有源目录都以斜杠结束,因此将其内容复制到目标目录。选项-d告诉它,不要递归复制。

    第二个技巧是rmdir /targetDirectory/*删除rsync创建的空目录(虽然我们没有要求它这样做)。

    我在这里测试过,删除源树中删除的文件就可以了。

答案 3 :(得分:0)

如果您可以制作文件列表,那么您已经解决了问题。 尝试:

find /path/to/src/ -name \*.mp3 > list.txt
rsync -avi --no-relative --progress --files-from=list.txt / user@server:/path/to/dest

如果再次为新文件运行脚本,它将只复制丢失的文件。

如果您不喜欢该列表,那么请尝试一句话(但它是另一种逻辑)

find /path/to/src/ -name \*.mp3 -type f \
  -exec rsync -avi --progress {} user@server:/path/to/dest/  \;

在这种情况下,您将每次询问每个文件,因为根据句子类型,您无法先构建文件列表。