我试图仅将其中包含 .mp3 文件的文件夹复制到另一台设备。并且只有其中的 .mp3。结构如下:
Band/Year - Album/*.flac
Band/Year - Album/*.txt
Band/Year - Album/*.mp3
Band/Year - Album/covers
Band/Year - Album/covers/*.jpg
我已经阅读了大量手册和论坛,但无法解决我的问题。无论我做什么,无论我如何尝试制定我想在复制中包含的内容,因为它被排除在外 - 它甚至消失了
--exclude=* --include=*
不会复制任何东西。我在另一个目录上测试了它,即使没有任何目录,该死。
编辑:我尝试过但无济于事的列表:
rsync -rnv --exclude=** --include=*/ --include=*/*/ --include=*/*/*/ --include=*/*/*.mp3 "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
rsync -rnv --exclude=** --include=*/ --include=*/*/ --include=*/*/*/ --include=**.mp3 "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
rsync -rnv --exclude=** --include=*/ --include=*/* --include=**.mp3 "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
rsync -rnv --exclude=*/*/* --include=**.mp3 "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
rsync -rnv --exclude=*/*/*.* --include=**.mp3 "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
rsync -rnv --exclude='*/*/*.*' --include='*/*/*.mp3' "./Be'lakor" /media/moorindal/WALKMAN/MUSIC
答案1
首先,为什么--exclude=* --include=*
不起作用:因为第一个匹配规则适用。*
匹配所有内容,因此所有内容都被排除,并且 rsync 甚至不会对任何文件尝试第二条规则。看Rsync 过滤器:仅复制一种模式有关 rsync 过滤器的指南。
要包含.mp3
文件,您需要
rsync -a -m --include='*.mp3' --include='*/' --exclude='*'
即包括 MP3,包括所有目录(如果不包括目录,则不包括其中的任何文件)并排除其他所有内容。该-m
选项(又名--prune-empty-dirs
)使 rsync 跳过不包含任何要复制的文件的目录。但这不会包含与该.mp3
文件位于同一目录中的其他文件。为此,您需要 shell 或其他工具的帮助。
在 zsh 中,您可以将.mp3
子目录中的文件与匹配**/*.mp3
,然后使用历史修改器作为一个全局限定符将结果转换为包含.mp3
文件的目录列表。
rsync -a **/*.mp3(:h) /destination
如果您有太多目录(或者更准确地说,如果它们名称的组合长度太大),这可能会打破命令行限制。删除重复项可能会有所帮助:
typeset -aU directories
directories=(**/*.mp3(:h))
rsync -a $directories /destination
这并不能消除命令过长的风险,而只是减少了风险。为了消除风险,请使用zargs
批量运行rsync。
autoload -U zargs
typeset -aU directories
directories=(**/*.mp3(:h))
do_rsync () { rsync -a $@ /destination; }
zargs --max-chars=$(($(get_conf ARG_MAX) - 500)) -- $directories -- do_rsync
答案2
您想用 rsync 做太多事情。首先要做的是生成所有 MP3 文件的列表。
find Music -type f -iname '*.mp3'
然后将文件列表转换为包含文件的目录列表。
sed 's:/[^/]*$::'
消除列表中任何重复的目录。
sort -u
现在您已获得所需的目录列表。一次将它们喂给 rsync 一个。使用 --relative 保持目标目录树完整。
while IFS= read -r dir; do rsync --archive --relative "$dir" /mnt; done
总共作为一个管道:
find Music -type f -iname '*.mp3' |
sed 's:/[^/]*$::' |
sort -u |
while IFS= read -r dir; do rsync --archive --relative "$dir" /mnt; done
答案3
您无需担心--include
或--exclude
为这种情况而烦恼。只需告诉rsync
复制mp3
位于结构良好的已知位置的文件即可:
cd /path/to/source
rsync -avR */*/*.mp3 /path/to/target/
也许您想复制包含mp3
.您可以通过这个小循环来做到这一点,再次假设结构良好的布局:
for mp3 in */*/*.mp3
do
rsync --exclude covers -avR "${mp3%/*}"/ /path/to/target/
done