touch——一个被大多数程序员误解的命令,你中招了吗?
误解
如果,你问一个程序员,touch 命令是干什么的?
我相信 10 个里面有 8 个会回答:创建一个空文件。
然而,事实真的如此吗?
本意
man touch
Linux man 手册里面介绍 到 touch - change file timestamps。所以,touch 的本意是改变文件的时间戳,即,将文件的访问时间和修改时间改为当前时间。
澄清
所以,创建一个空文件,只是 touch 的功能只一:当文件不存在时,使用当前时间创建一个空文件。
甚至,创建空文件你仍然可以理解为是改变文件的时间戳,改变为现在,也就从无到有创建了。另一种理解,一个文件不可能只有访问时间和修改时间而没有创建时间(那太邪乎了),而 touch 为了完成修改文件的访问时间和修改时间,不得已要给文件一个创建时间,就这样(误打误撞)把一个文件给创建了。
以上内容纯属瞎扯,哈哈!『Talk is cheap. Show me the code』 😋
源码
/* Update the time of file FILE according to the options given.
Return 0 if successful, 1 if an error occurs. */
static int touch(const char *file)
{
...
/* 文件不存在先创建 */
if (!no_create) {
/* Try to open FILE, creating it if necessary. */
fd = open(file, O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
/* Don't save a copy of errno if it's EISDIR, since that would lead
touch to give a bogus diagnostic for e.g., `touch /' (assuming
we don't own / or have write access to it). On Solaris 5.6,
and probably other systems, it is EINVAL. On SunOS4, it's EPERM. */
if (fd == -1 && errno != EISDIR && errno != EINVAL && errno != EPERM)
open_errno = errno;
}
...
/* 更新文件的访问时间和修改时间 */
if (amtime_now) {
/* Pass NULL to utime so it will not fail if we just have
write access to the file, but don't own it. */
status = utime(file, NULL);
} else {
struct utimbuf utb;
/* There's currently no interface to set file timestamps with
better than 1-second resolution, so discard any fractional
part of the source timestamp. */
if (use_ref) {
utb.actime = ref_stats.st_atime;
utb.modtime = ref_stats.st_mtime;
} else
utb.actime = utb.modtime = newtime;
if (!(change_times & CH_ATIME))
utb.actime = sbuf.st_atime;
if (!(change_times & CH_MTIME))
utb.modtime = sbuf.st_mtime;
status = utime(file, &utb);
}
...
return 0;
}
从源码中可以清楚看到,touch 先检测文件是否存在,不存在就先创建,然后使用 utime() 系统调用,修改文件的访问时间和修改时间。