我正在尝试清理所有音乐文件夹(有很多) - 但我不想删除,而是想移动那些空的、或者只有几 Mb 的、或者只有几个文件的文件夹。
我设法使用以下find
命令来移动所有空目录:
find . -empty -type d -exec mv {} /share/Container/beetsV2/music/my_empty_folders \;
...但我似乎无法弄清楚如何根据大小查找目录。我认为以下内容会起作用,但事实并非如此;它的回报似乎比预期的要多。
find . -size -5M -type d -exec mv {} /share/Container/beetsV2/music/my_folders_under_5Mb \;
当涉及到查找仅包含几个文件的目录时,我似乎找不到单个命令行来执行上述操作。存在吗?
答案1
从man find
:
-size n[cwbkMG] 文件使用少于、多于或恰好 n 个单位的空间,向上舍入。
此开关与目录无关磁盘使用情况。
解决方法是使用bash
处理find
输出中的所有目录,获取每个目录的大小,mv
如果大小小于 N MiB,则获取每个目录的大小:
move_dirs_smaller_than() {
export MAX=$(($1*1024)) # $1 is in MiB
export path=$2 # $2 /path must be outside of .
find . -mindepth 1 -type d -exec bash -c '
read size _ < <(du -sk "$1")
((size < MAX)) && echo mv -- "$1" "$path"
' bash {} \; -prune
}
echo
当输出看起来足够好时删除语句。
5MiB 的函数用法:
/path
应该不是在当前目录中(或使用find ! ./dir
):
move_dirs_smaller_than 5 /path
查看find
有关 的手册页-prune
,-mindepth
并-maxdepth
根据您的需要。
答案2
GNU 实现du
可以为您提供以下报告:
- 累积磁盘使用量(默认)
- 累积大小与
--apparent-size
- 文件(任何类型)的累积数量
--inode
对于目录及其内容(不幸的是,它不能在一份报告中包含所有三个内容)。
您还可以告诉它不要使用 -l
/删除重复的硬链接--count-links
。
它是少数可以可靠地对输出进行后处理的产品之一,因为它有一个-0
/--null
选项来输出 NUL 分隔的记录。
因此,如果您使用的是 GNU 系统,您可以这样做:
xargs -r0a <(
du --inode --null --count-links | # count inodes
tac -s '' | # reverse the output so parents are shown before children
perl -0lnse '
if (
m{^(\d+)\t(.*)}s &&
$1 < $max &&
rindex($2, "$last_moved/", 0) < 0 # not a subdirectory of the last moved
) {
print($last_moved = $2);
}' -- -max=10
) echo mv -it /path/to/destination --
这将移动包含(递归地)少于 10 个文件的目录(任何类型,包括目录,也包括目录本身)。
替换--inode
为--apparent-size --block-size=1
(或-b
简称)以考虑累积大小而不是文件数量。与磁盘使用情况相同--apparent-size
(您需要-max
相应更新)。
如果对结果满意,请删除echo
以实际执行。
所有-r
, -0
, -a
, --inode
, --apparent-size
, -l
, --count-links
, tac
, -b
, --block-size
,-t
都是非标准 GNU 扩展,其中很少有已添加到这些标准实用程序的其他实现中,因此不要指望它们可以在 GNU 系统之外工作,除非您已经安装了 GNUcoreutils
并且findutils
那里。既然您已经使用了 linux 标签,那么您很有可能使用的是 GNU 系统。
要考虑文件数量和累积大小,您可以使用 GNU find
,它有一个-printf
谓词可以报告文件类型和大小并手动求和:
xargs -r0a <(
find . -depth -printf '%y %s %p\0' | perl -0lsne '
if (m{^(\S+) (\d+) ((.*)/.*)}s) {
my ($type, $size, $file, $parent) = ($1, $2, $3, $4);
$count{$parent} += ++$count{$file};
$size{$parent} += $size{$file} += $size;
unshift @dirs, $file if $type eq "d";
}
END {
for $dir (@dirs) {
if (
$size{$dir} < $max_size &&
$count{$dir} < $max_count &&
rindex($dir, "$last_moved/", 0) < 0
) {
print $last_moved = $dir;
}
}
}' -- -max_count=10 -max_size="$(( 5 * 1024 * 1024 ))"
) echo mv -it /path/to/destination --
对于磁盘使用情况而不是表观大小,请将其替换%s
为%b
您必须乘以 512(替换$2
为$2 * 512
上面)以获得以字节为单位的磁盘使用情况。