我正在尝试创建一个脚本,可以执行该脚本来搜索文件列表,将文件大小字段与指定的文件大小进行比较,然后显示小于指定文件大小的文件。
我知道我必须使用“ls -l”才能获取详细的文件列表。但是,我该如何搜索列表并提取文件呢?
答案1
你的方法很笨拙(公平地说错误的)。find
其中之一就是有专门的工具来完成此类任务。
例如,要递归查找当前目录中小于 1 MiB(1048576 字节)的所有文件:
find . -type f -size -1048576c
或者使用提供此类基于大小的 glob 限定符的 shell,例如zsh
,递归地:
print -rl -- **/*(.L-1048576)
这里,与上面相反find
,没有隐藏文件。添加D
glob 限定符以包含它们。
答案2
解析 的输出时要记住的事情ls -l
:
- 格式取决于区域设置。该格式仅由 POSIX/C 语言环境中的 POSIX 指定,即使如此,它也允许一些变化(例如字段之间的间距、第一个字段的宽度...)。例如,您无法轻松检测以空白字符开头的可移植文件名。
- 许多系统允许用户名和组名中存在空格,这使得可靠地解析输出几乎是不可能的。最好是使用
ls -n
(使用数字用户 ID)而不是ls -l
. ls
如果文件名可能包含换行符(并且几乎所有 POSIX 系统中的文件名中都允许换行符),则不可能可靠地解析 的输出,除非您使用该-q
选项(但是您无法说出确切的文件名,只需查看引用的表示形式,您无法从中返回原始文件名)或使用某些实现中发现的非标准选项。但另请参阅下面的技巧。- 这尺寸并非所有类型的文件都提供该字段(并且该字段的含义尺寸对于某些类型的文件,字段因系统而异)。您可能希望限制为常规文件。
- 以上假设是 POSIX
ls
。已知旧版本具有不同的输出格式,或者在某些情况下字段之间缺少空格......
因此,考虑到这一点,只要您可以保证文件名不包含换行符并且不以空白字符开头,要列出大小严格小于 1MiB 的常规文件,您可以这样做:
(
export LC_ALL=C
ls -n | awk '
/^-/ && $5 < 1048576 {
gsub(/([^[:blank:]]+[[:blank:]]+){8}/, "")
print
}'
)
-a
如果您想包含隐藏文件,请添加该选项。添加-L
如果对于符号链接,您想要考虑它们(最终)解析到的文件。
正如其他人所说,正确的解决方案是在find
这里使用。
避免换行和前导空白问题的技巧。
ls -n
如果我们使用代替ls -nd ./*
,我们将能够知道文件名从哪里开始(在 上./
)以及在哪一行结束(在下一个 之前的行上./
),所以你可以这样做:
(
export LC_ALL=C
ls -nd ./* | awk '
/\// {
selected = (/^-/ && $5 < 1048576)
sub(/.*\//, "./")
}
selected'
)
但请注意,如果当前目录中有大量文件(当./*
shell 扩展时),则该方法将不起作用,这可能会导致达到参数数量的限制。
要包含隐藏文件,-a
在这里没有帮助,我们需要告诉 shell 展开它们。 POSIXly,它有点笨拙:
ls -dn ./..?* ./.[!.]* ./*
(这可能会导致有关丢失./..?*
或./.[!.]*
文件的警告消息)。
答案3
由于您只想解析ls's
输出,因此您可以找到regular files
大小小于上限 ( MAX bytes
) 的文件,并且ASSUMING
文件名中没有空格/换行符,您可以执行以下操作:
/bin/ls -l | awk -v MAX=150 '/^-/ && $5 <= MAX { print $NF }'