diff --git a/Base/usr/share/man/man1/find.md b/Base/usr/share/man/man1/find.md index b4f19b865e..127e476f18 100644 --- a/Base/usr/share/man/man1/find.md +++ b/Base/usr/share/man/man1/find.md @@ -32,9 +32,18 @@ specified commands, a `-print` command is implicitly appended. name, a numerical UID may be specified. * `-group name`: Checks if the file is owned by the given group. Instead of a group name, a numerical GID may be specified. -* `-size number[c]`: Checks if the file has the given size in 512-byte blocks, - rounded up. If the size is followed by the `c` character, checks if the file - has the given size in bytes. +* `-size number[bcwkMG]`: Checks if the file uses the specified `n` units of +space rounded up to the nearest whole unit. + + The unit of space may be specified by any of these suffixes: + + * `b`: 512-byte blocks. This is the default unit if no suffix is used. + * `c`: bytes + * `w`: two-byte words + * `k`: kibibytes (1024 bytes) + * `M`: mebibytes (1024 kibibytes) + * `G`: gibibytes (1024 mebibytes) + * `-name pattern`: Checks if the file name matches the given global-style pattern (case sensitive). * `-iname pattern`: Checks if the file name matches the given global-style diff --git a/Userland/Utilities/find.cpp b/Userland/Utilities/find.cpp index cc47399467..d1e4a2094c 100644 --- a/Userland/Utilities/find.cpp +++ b/Userland/Utilities/find.cpp @@ -226,28 +226,51 @@ public: SizeCommand(char const* arg) { StringView view { arg, strlen(arg) }; - if (view.ends_with('c')) { - m_is_bytes = true; + auto suffix = view[view.length() - 1]; + if (!is_ascii_digit(suffix)) { + switch (suffix) { + case 'c': + m_unit_size = 1; + break; + case 'w': + m_unit_size = 2; + break; + case 'k': + m_unit_size = KiB; + break; + case 'M': + m_unit_size = MiB; + break; + case 'G': + m_unit_size = GiB; + break; + case 'b': + // The behavior of this suffix is the same as no suffix. + break; + default: + fatal_error("Invalid -size type '{}'", suffix); + } + view = view.substring_view(0, view.length() - 1); } - auto number = view.to_uint(); - if (!number.has_value()) + auto number = view.to_uint(); + if (!number.has_value() || number.value() > AK::NumericLimits::max()) fatal_error("Invalid size: \033[1m{}", arg); - m_size = number.value(); + m_number_of_units = number.value(); } private: virtual bool evaluate(const struct stat& stat) const override { - if (m_is_bytes) - return stat.st_size == m_size; + if (m_unit_size == 1) + return stat.st_size == m_number_of_units; - auto size_divided_by_512_rounded_up = (stat.st_size + 511) / 512; - return size_divided_by_512_rounded_up == m_size; + auto size_divided_by_unit_rounded_up = (stat.st_size + m_unit_size - 1) / m_unit_size; + return size_divided_by_unit_rounded_up == m_number_of_units; } - off_t m_size { 0 }; - bool m_is_bytes { false }; + off_t m_number_of_units { 0 }; + off_t m_unit_size { 512 }; }; class NameCommand : public Command {