![如何仅在特定文件具有特定大小时运行命令](https://linux22.com/image/220306/%E5%A6%82%E4%BD%95%E4%BB%85%E5%9C%A8%E7%89%B9%E5%AE%9A%E6%96%87%E4%BB%B6%E5%85%B7%E6%9C%89%E7%89%B9%E5%AE%9A%E5%A4%A7%E5%B0%8F%E6%97%B6%E8%BF%90%E8%A1%8C%E5%91%BD%E4%BB%A4.png)
如何仅在某个文件超过定义的大小时才执行命令?两者最终都应该作为 crontab 中的单行代码运行。
伪代码:
* * * * * find /cache/myfile.csv -size +5G && echo "file is > 5GB"
答案1
如果你有 GNU stat
,你可以使用它的--printf
选项来获取它的大小。
例如
size=$(stat --printf '%s' /cache/myfile.csv)
if [ "$size" -gt 5368709120 ] ; then # 5 GiB = 5 * 1024 * 1024 * 1024
echo "file is > 5GB"
fi
man stat
详情请参阅。
BSD stat
(例如在 FreeBSD 和 Mac 上)具有类似的格式化选项-f
:
size=$(stat -f '%z' /cache/myfile.csv)
或者,您可以使用 perl 的内置stat
函数或其-s
文件测试运算符(与 bash 的文件测试类似-s
,但它返回文件的大小,而不仅仅是在文件存在且非空时返回 true)。 perl 的 stat 函数返回有关包含以下数据的文件的元数据的 13 元素列表(数组)(从 复制perldoc -f stat
):
[...] Not all fields are supported on all filesystem types. Here are
the meanings of the fields:
0 dev device number of filesystem
1 ino inode number
2 mode file mode (type and permissions)
3 nlink number of (hard) links to the file
4 uid numeric user ID of file's owner
5 gid numeric group ID of file's owner
6 rdev the device identifier (special files only)
7 size total size of file, in bytes
8 atime last access time in seconds since the epoch
9 mtime last modify time in seconds since the epoch
10 ctime inode change time in seconds since the epoch (*)
11 blksize preferred I/O size in bytes for interacting with the
file (may vary from file to file)
12 blocks actual number of system-specific blocks allocated
on disk (often, but not always, 512 bytes each)
(The epoch was at 00:00 January 1, 1970 GMT.)
字段 7 就是我们需要的字段。
要返回文件的大小(以便稍后在 shell 命令或脚本中使用),请使用stat
:
# stat
perl -e 'print scalar((stat(shift))[7])' /cache/myfile.csv
# -s
perl -e 'print -s shift' /cache/myfile.csv
或者用 perl 完成这一切:
# stat
perl -e 'print "File is > 5 GiB\n" if (stat(shift))[7] > 5*1024*1024*1024' /cache/myfile.csv
# -s
perl -e 'print "File is > 5 GiB\n" if -s shift > 5*1024*1024*1024' /cache/myfile.csv
请参阅perldoc -f stat
and perldoc -f -X
(以及help test
bash 中的)。
顺便说一句,perl 的shift
函数删除数组的第一个元素(默认情况下@ARGV
,如果未指定,则为命令行参数数组)并返回其值。它经常在循环中使用来处理数组的所有元素,但这里我们只对第一个参数(文件名)感兴趣。perldoc -f shift
详细信息请参见参考资料,包括有关词法范围和在子例程中使用的注释。
答案2
要使用文件大小作为前提条件,您可以使用stat
或者find
:
[ -n "$(find /cache/myfile.csv -prune -size +5G 2>/dev/null)" ] && echo "file is > 5GB"
或者,如果目标命令(echo
此处为 )很短,则将其放入exec
“find”部分
find /cache/myfile.csv -prune -size +5G -exec echo "file is > 5GB" \;
以防-prune
万一myfile.csv
是目录类型的文件,以防止find
下降到其中。
答案3
如果您需要在 shell 中处理文件,则两个版本仅在满足所有条件时才执行 shell 的命令:是一个文件、已命名myfile.csv
且 > 5G:
find /cache -name 'myfile.csv' -type f -size +5G -exec bash -c '
echo "$1 is > 5GB"
' bash {} \;
或者
find /cache -name 'myfile.csv' -type f -size +5G -exec bash -c '
for file; do echo "$file is > 5GB"; done
' bash {} +
答案4
请注意,某些 shell 具有内置功能。
SHELL=/bin/tcsh
* * * * * if (-Z /cache/myfile.csv > 5*1024*1024*1024) echo 'file is > 5GiB'
或者使用zsh
,这里使用 glob 限定符和匿名函数,尽管 zsh 也有一个stat
早于 GNU 和 BSD 的内置函数stat
:
SHELL=/bin/zsh
* * * * * (){ if (($#)) echo 'file is > 5GiB'; } /cache/myfile.csv(NLG+5)
(请注意,与 for 一样find -size +5G
,我们在这里讨论的是千兆字节(1GiB = 1,073,741,824 字节),而不是千兆字节(1GB = 1,000,000,000 字节))
对于符号链接,tcsh
将获取它最终解析为的文件的大小,而像s 这样zsh
的LG+5
限定符将检查符号链接本身的大小。更改为检查符号链接解析后的大小。的内置函数默认在符号链接解析后为您提供信息,以更改它。在 GNU 和 BSD 中,情况正好相反。与where告诉它遵循符号链接相同。find
-size
-LG+5
zsh
stat
-L
stat
find
-L
有关获取文件大小的更多方法,请参阅如何在 bash 脚本中获取文件的大小?