我试图递归地找到目录中最大的文件。如果该目录内有子目录,则该函数需要进入该目录并检查最大的文件是否在那里。一旦找到最大的文件,输出就会显示,其中包含相对路径名以及最大文件的名称和大小。
前任:
dude@shell2 (~...assignment/solutions) % bash maxfile.sh ~/test
class/asn
dude.h.gch: 9481628
这就是我所拥有的:
#!/bin/sh
clear
recursiveS() {
for d in *; do
if [ -d $d ]; then
(cd $d; echo $(pwd)/$line; du -a; recursiveS;)
fi
done
}
recursiveS
我已经被困了一段时间了。我无法通过管道化许多现有的 Unix 工具来实现这一点。任何想法都会很好!
答案1
使用find
(这里假设 GNU find
)输出文件名和文件大小。种类。打印出最大的一个。
find . -type f -printf "%s\t%p\n" | sort -n | tail -1
假设文件路径不包含换行符。
bash
在 GNU 实现中使用循环stat
:
shopt -s globstar
max_s=0
for f in **; do
if [[ -f "$f" && ! -L "$f" ]]; then
size=$( stat -c %s -- "$f" )
if (( size > max_s )); then
max_s=$size
max_f=$f
fi
fi
done
echo "$max_s $max_f"
这将比查找解决方案慢得多。这还假设文件名不以换行符结尾,并且将跳过隐藏文件并且不会进入隐藏目录。
如果当前目录中有一个文件被调用-
,则将考虑在标准输入上打开的文件的大小。
请注意,4.3 之前的版本bash
在下降目录树时遵循符号链接。
答案2
此命令也有助于列出定义的大小。
find . -type f -size +100M -exec ls -lh {} \;
答案3
这适用于 BSD/macOS 并使用快速但非 POSIX 的实用程序-ls
扩展find
:
find . -type f -ls | sort -k7 -r | head -n 3
这速度较慢,但可能适用于-ls
扩展在以下位置不可用的POSIX 系统find
:
find . -type f -exec ls -al {} \; | sort -k5 -r | head -n3
怎么运行的:
find
是一个功能强大的文件搜索实用程序,它将根据下面解释的给定查询向您显示结果。find .
将在当前工作目录中搜索。find . -type f
将仅搜索指定的文件类型“f”,即常规文件(这意味着它将跳过目录、特殊文件、链接、套接字等)。-ls
开关将指示find
显示有关找到的文件的完整信息。然而,根据 BSD 系统上的 man 的说法,它是 IEEE Std 1003.1-2001(“POSIX.1”)标准的扩展,可能不适用于所有平台。- 或者,如果
-ls
扩展在您的系统上不可用,您可以-exec .. {} \;
使用ls -al
命令并使用第 5 个字段对结果进行排序。{}
表示已找到的文件名。\;
包含-exec
命令。 |
Unix 符号的意思是“管道”,即将一个程序的输出重定向到另一个程序的输入。它将发送find
程序输出文本作为sort
程序的输入。sort
是一个排序实用程序。它获取数据行,然后按升序对这些行进行排序作为结果。sort -k7
表示将第7个字段作为排序参数值。参数由空格分隔。第 7 个参数是实用程序生成的文件大小find
。如果你使用-exec ls -al {} \;
而不是-ls
那么你将使用第五个字段-k5
来排序。-r
告诉sort
使用反向排序,将最大的放在前面。因为我们想首先查看最大的文件。- 此外,如果您确实不想看到数百行,您还可以
|
将排序的输出通过管道 ( ) 传输到head
实用程序,该实用程序将只显示结果输出的前三行(按照 的指示)。-n 3
长话短说:用于查找递归常规文件,仅在当前工作目录中开始搜索,然后使用扩展名(或执行)find
显示有关该文件的完整信息。稍后使用 unix 管道将结果传递给to ,并根据第 7 个(或第 5 个)字段使其首先排序最大。此外,您可以使用实用程序将结果限制为行。-ls
ls -al
find
sort
|
n
head
我的意思是“使用 Brainz”让你阅读“man”并自己离线搜索解决方案,这将训练你从头开始解决问题:-)
答案4
此外斯蒂芬·查泽拉斯' 回复,我想添加以下注释(我无法发表评论):
- 要获得最小的常规文件,请使用
o
而不是O
:
ls -ld -- **/*(.DoL[1])
- 您可以通过将具体(或多个)扩展名附加到通配符来进行过滤
**/*
:
ls -ld -- **/*.png(.DoL[1])
ls -ld -- **/*.{png, jpg}(.DoL[1]) # this will give two results, one per extension