我的计算机(Ubuntu 22.04)上有很多包含 MP3 文件的目录,例如我的/home
、、/data
某些分区等。我想通过将所有这些目录(大多数目录以音乐专辑名称命名......)移动到一个 MP3 目录中来重新分组/合并它们。
我知道要查找.mp3
文件 ( find -iname '*.mp3'
) 中的谁,也知道如何移动find
( -exec mv
) 找到的文件。但是,我不知道如何移动包含找到的数据的目录。
任何想法?
答案1
您可以使用以下 bash 管道:
find /path/to/src -iname '*.mp3' -type f -printf '%h\0' |
perl -0e 'print sort{length($b)<=>length($a)}keys%{{map {$_,1}<>}}' |
xargs -0 echo mv --backup=t -t /path/to/dst
它执行以下操作:
\0
并且-0
将使用空分隔符而不是换行符来处理奇怪的目录名称。find /path/to/src
列出以下所有内容src
-iname '*.mp3'
.mp3
扩展的过滤器-type f
以某种方式排除带有该扩展名的文件夹-printf '%h\0'
获取文件所在的目录
perl -0e 'print ...'
运行脚本:sort{length($b)<=>length($a)}
通过将较长的路径移至顶部来避免错误,以便子目录在其父目录之前移动keys%{{map {$_,1}<>}}
删除重复项,即当一个目录有两个或多个.mp3
文件时
xargs
获取每个输入行(即目录)并将其作为参数提供给命令echo
你应该在检查这是你想要的之后删除它mv -t /path/to/dst
将文件移动到目标。-t
让我们在源文件系统路径之前指定目标目录,以便将xargs
路径放在末尾。--backup=t
当不同位置有两个同名的目录时,对目录进行编号
即使父目录包含 ,也会先将子目录移出.mp3
。如果您(像@PeterCordes)想要更改此行为,只需在 perl 脚本中交换$a
和$b
即可。这将反转排序,以便先移动父目录。有关不再存在的父目录的其余错误可以忽略或用最后的 来消除2>/dev/null
。感谢@Raffa 所做的许多改进。
示例设置
./src
./src/a
./src/a/a
./src/a/a/a
./src/a/a/a/a.mp3
./src/a/a.mp3
./src/d
./src/d/other.txt
./src/helloworld
./src/helloworld/c.mp3
./dst
示例结果
./src
./src/d
./src/d/other.txt
./dst
./dst/a
./dst/a/a
./dst/a/a.mp3
./dst/a.~1~
./dst/a.~1~/a.mp3
./dst/helloworld
./dst/helloworld/c.mp3