我正在尝试将我目录中所有 xml 文件的时间戳更新为当前时间(递归)。我使用的是 Mac OSX 10.8.5。
在大约 300,000 个文件上,以下echo命令需要10 秒:
for file in `find . -name "*.xml"`; do echo >> $file; done
Run Code Online (Sandbox Code Playgroud)
但是,以下touch命令需要10 分钟!:
for file in `find . -name "*.xml"`; do touch $file; done
Run Code Online (Sandbox Code Playgroud)
为什么这里的回声比触摸快得多?
Chr*_*own 164
在 bash 中,touch是一个外部二进制文件,但它echo是一个内置的 shell:
$ type echo
echo is a shell builtin
$ type touch
touch is /usr/bin/touch
Run Code Online (Sandbox Code Playgroud)
由于touch是外部二进制文件,并且您touch每个文件调用一次,因此 shell 必须创建 300,000 个 实例touch,这需要很长时间。
echo但是,它是一个 shell 内置函数,shell 内置函数的执行根本不需要 fork。相反,当前的 shell 会执行所有操作,并且不会创建任何外部进程;这就是为什么它要快得多的原因。
下面是 shell 操作的两个配置文件。您可以看到,在使用touch. 使用/bin/echo而不是 shell 内置应该显示更具可比性的结果。
$ strace -c -- bash -c 'for file in a{1..10000}; do touch "$file"; done'
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
56.20 0.030925 2 20000 10000 wait4
38.12 0.020972 2 10000 clone
4.67 0.002569 0 80006 rt_sigprocmask
0.71 0.000388 0 20008 rt_sigaction
0.27 0.000150 0 10000 rt_sigreturn
[...]
Run Code Online (Sandbox Code Playgroud)
$ strace -c -- bash -c 'for file in b{1..10000}; do echo >> "$file"; done'
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
34.32 0.000685 0 50000 fcntl
22.14 0.000442 0 10000 write
19.59 0.000391 0 10011 open
14.58 0.000291 0 20000 dup2
8.37 0.000167 0 20013 close
[...]
Run Code Online (Sandbox Code Playgroud)
Gra*_*eme 74
正如其他人回答,使用echo会比更快touch的echo是内置到shell命令它通常是(但并非规定)。使用它可以省去与为您获得的每个文件启动一个新进程相关的内核开销touch。
但是,请注意,实现此效果的最快方法仍然是使用touch,而不是为每个文件运行一次程序,而是可以使用-execwith 选项find来确保仅运行几次。这种方法通常会更快,因为它避免了与 shell 循环相关的开销:
find . -name "*.xml" -exec touch {} +
Run Code Online (Sandbox Code Playgroud)
如果可能,使用+(而不是\;) withfind ... -exec将每个文件作为参数仅运行一次命令。如果参数列表很长(如 300,000 个文件的情况),将使用长度接近限制的参数列表进行多次运行(ARG_MAX在大多数系统上)。
这种方法的另一个优点是它对包含所有空白字符的文件名表现得很好,而原始循环的情况并非如此。
dev*_*ull 29
echo是一个内置的shell。另一方面,touch是外部二进制文件。
$ type echo
echo is a shell builtin
$ type touch
touch is hashed (/usr/bin/touch)
Run Code Online (Sandbox Code Playgroud)
Shell 内置函数要快得多,因为在加载程序时不涉及任何开销,即不涉及fork/ exec。因此,在大量执行内置命令与外部命令时,您会观察到显着的时间差异。
这就是诸如此类time的实用程序可用作 shell 内置函数的原因。
您可以通过以下方式获取 shell 内置函数的完整列表:
enable -p
Run Code Online (Sandbox Code Playgroud)
如上所述,使用实用程序而不是内置程序会导致显着的性能下降。以下是使用内置 echo和实用程序 创建约 9000 个文件所花费的时间的统计信息echo:
# Using builtin
$ time bash -c 'for i in {1000..9999}; do echo > $i; done'
real 0m0.283s
user 0m0.100s
sys 0m0.184s
# Using utility /bin/echo
$ time bash -c 'for i in {1000..9999}; do /bin/echo > $i; done'
real 0m8.683s
user 0m0.360s
sys 0m1.428s
Run Code Online (Sandbox Code Playgroud)