有几种方法可以完全截断文件,通常适用于大多数符合POSIX标准的操作系统。你在shell脚本中看到最常见的是像true > file.txt
或: > file.txt
这样的东西(在bash
shell的情况下,仅使用>
重定向就足够了)。这是因为>
通过open()
或openat()
系统调用以O_WRONLY|O_CREAT|O_TRUNC
标志打开文件的方式 - 这读取只写OR创建(如果文件名不存在)OR截断现有文件名。
有了这个想法,我们可以自己在C中实现类似的东西:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv){
if (argc == 2){
int fd = open(argv[1],O_TRUNC);
close(fd);
}
return 0;
}
将存储此代码的文件命名为
trunc.c
,并使用
gcc trunc.c -o trunc
进行编译,这样您就拥有了一个小型实用程序,可以截断作为文件名参数提供的文件名,例如
trunc ./foobar.txt
。当然,此代码不会进行其他检查,它只会截断第一个位置参数。我将让读者自行解决如何处理多个位置参数的问题。另外,还有
truncate()
系统调用,我们也可以使用它来将文件截断为可变长度。
现在,如果您不喜欢C语言,Python可能更容易上手。在Python中,
open()
命令的操作原理与之相同-打开文件以进行写入,并在文件名存在时进行截断。因此,我们可以这样做:
python -c 'import sys;open(sys.argv[1],"w").close()' passwd.copy
关于查找所有的.log文件,这个问题已经在其他答案中提到了 - 在bash中使用*通配符或扩展通配符。还有一个命令是find -type f -name "*.log",它有一个-exec标志用于运行命令(在这种特殊情况下,使用sh -c ''来利用>,因为>是一个shell操作符而不是外部可执行程序)。因此,你可以这样做
find /var/log -type f -name "*.log" -exec sh -c 'true > "$1"' sh {} \;
值得注意的是,目录中的日志文件(例如
/var/log
)通常会被logrotate服务进行轮转,因此会出现诸如
/var/log/service.log
、
/var/log/service.log.1
等文件名,因此您可能希望使用
*.log.[1-9]
模式。
除此之外,我们还可以将
/dev/null
复制到所需的文件中。奇怪的是,尽管
/dev/null
是一个特殊字符设备类型的文件,但当你将其复制到其他地方时,结果是一个空的普通文件,至少在GNU
cp
中是如此。因此,我们可以这样做:
cp /dev/null foo.txt
或者
dd if=/dev/null of=foo.txt
其他建议阅读:
- [什么是 ">" 和 ">>" 的区别?]({{link1}})
- [Python 的 open 函数文档]({{link2}})
- [如何清理日志文件]({{link3}})
- [清空文件内容]({{link4}})
/var/log
是系统存放可能以后会用到的消息的地方。Ubuntu之前遇到过这个问题。阅读man 8 logrotate;man logrotate.conf
。 - waltinator