Bash 脚本按大小列出目录中的项目

Bash 脚本按大小列出目录中的项目

如何编写一个脚本,对于每个参数,脚本应显示目录中最大的项目及其大小。像这样的东西:

[user]$ maxls /boot 2> /dev/null | sort -n
1024 /boot/grub2/themes/stars
8101 /boot/grub2/pic.png

答案1

#!/bin/sh
for dir
do
    [ -d "$dir" ] || continue
    du -hs "$dir"/* | sort -hr | sed  1q
done

答案2

使用perl我会选择这样的东西:

#!/usr/bin/env perl
use strict;
use warnings;

use File::Find;

my %biggest_file_in;
my %biggest_file_size_in;

sub max_in_path {
    my ($dir) = @_;
    return unless -f;
    if ( -s > ( $biggest_file_size_in{$dir} // 0 ) ) {

        $biggest_file_in{$dir}      = $File::Find::name;
        $biggest_file_size_in{$dir} = -s;
    }
}


my ($path_to_search) = @ARGV;
die "Specify a path" unless $path_to_search;
foreach my $dir ( glob("$path_to_search/*") ) {
    next unless -d $dir;
    find( sub { max_in_path($dir) }, $dir );
    print $dir, ":", $biggest_file_in{$dir}, " =>",
        $biggest_file_size_in{$dir}, "\n";
}


print "Largest files in individual directories (sorted):\n";
foreach my $dir ( sort 
                     { $biggest_file_size_in{$b} <=> $biggest_file_size_in{$a} } 
                         keys  %biggest_file_size_in ) { 
    print "$dir $biggest_file_in{$dir} $biggest_file_size_in{$dir}\n";
}

注意 - 适用于指定目录下的所有目录。 (例如: myfind.pl /data将搜索/data/*- 但忽略 中存在的任何文件/data);

答案3

shellzsh对此有内置支持:

#! /bin/zsh -
zmodload zsh/stat &&
for dir {
  largest=(${dir:-.}/**/*(NDOL[1]))
  (($#largest)) || largest=${dir:-.}
  zstat -A size +size -- "$largest" &&
    print -r -- $size $largest
}

答案4

# m_all [dir=.]...: lists the biggest file in *all* the directories.
#   du options can be specified using $DU_OPTS; the recommend value is '-h'.
m_all(){ find "$@" -type f -print0 | du $DU_OPTS --files0-from=-; }
# maxls: for each argument, list the biggest $maxls_n items.
#   If $maxls_n is undefined or empty, use 1.
#   Additional arguments to pass to m_all can be defined in the array mallargs; see examples below.
maxls(){ local i; for i; do m_all "$i" "${mallargs[@]}" | sort -h | tail -n "${maxls_n:-1}"; done; }
#_Example:
# list the biggest file for /bin and /usr respectively
maxls /bin /usr
# list the biggest 5 files for /home and /root
maxls_n=5 maxls /home /root
# Let maxls count only *.avi, *.svg and *.mp4:
mallargs=(-iregex '.*\.\(avi\|svg\|mp4\).*')
# And run it against ~/Anime
maxls ~/Anime; mallagrs=() # clear that setting
# And use m_all to list the biggest five logs:
DU_OPTS=-h m_all /var -name '*.log*' | sort -h | tail -n 5

您甚至可以添加find过滤器!

编辑: 为每个添加。感谢 RobertL 指出了这一点。和文档。

如果您希望将其作为脚本,请创建一个新文件,其中包含#!/bin/bash,将这些行复制到(){其中,然后添加maxls "$@".但就我个人而言,我不喜欢~/bin用超级琐碎的脚本来填充我的脚本。


说明/变更日志

从示例中我们可以看到子目录中的文件,并且使用额外的sort -h.由于整个目录绝对不小于其中包含的文件,因此我得出结论项目仅限于文件。

从此时起,我得到了最初的解决方案,现在称为m_all.除非我们对它们进行排序,否则我们无法知道哪些是最大的,因此tail在最初的示例中添加了额外的传递。

经过一些修补,这是版本 3,但这有问题,因为提问者想要对于每个参数。我将其重命名为m_all,留下一个名为 的包装器,maxls因为我认为旧的包装器仍然有一些用途,并且我想最小化我的更改(v4)。正如我一贯所做的那样,我留下了一些开关来改变它的行为。之后,如您所见,添加了文档 (v5-7)。

请注意,随着foreach行为,在整个事情完成后使用任何tail或通常是没有意义的。每次获得这些输出时都sort必须使用。确实会打印给定每个文件的最后几行,但这会使代码变得超长。sorttail

相关内容