自动触摸文件的 shell 脚本

自动触摸文件的 shell 脚本

我编写了一个 shell 脚本来访问目录中的所有文件/tmp。然而,有一条错误消息说 /bin/touch: Argument list too long。问题的原因是什么?

#!/bin/bash

dayNo=1
while test $dayNo -le 200
do
    touch `find /tmp/`
    sleep 86000
done

答案1

/tmp你的文件太多了不适合一次在命令行上显示所有名称(如果任何路径中有空格,您拥有的版本也是不安全的)。

好消息是,find可以安全、正确地为您执行此操作:

find /tmp -exec touch -c '{}' +

将像以前一样找到所有文件,然后touch根据每次需要运行尽可能多的文件来运行多次。

find-exec选项接受一个命令来运行匹配的文件并替换路径{}+意味着它一次对多个文件运行该命令,或者对每个文件\;运行一次。touch


正如评论中所指出的,-execdir touch -c '{}' \;这里严格来说更安全,尽管它可能会慢一些,并且在单用户系统上没有太多好处。它通过首先切换到每个子目录,然后每次仅针对该目录中的文件运行命令来避免某些竞争条件。该-execdir选项是非标准扩展,但受支持GNU,自由BSD,开放BSD,网络BSD, 和操作系统 finds;其他商业Unices一般没有它。我不确定您正在使用什么,但如果适用,请考虑上述内容。

答案2

shell 将反引号中表达式的结果替换到该行中。但是系统对命令的参数列表的长度有限制。因此,如果 /tmp 中有几千个文件,它会尝试创建一个包含数千个名称作为参数的命令。这失败了。

有几种方法可以更轻松地做到这一点。发现本身可以运行命令。大多数现代版本将允许您拆分它并运行多个单独的touch命令,每个命令都在限制之下。

find /tmp -exec touch {} +

答案3

问题中反引号调用的主要问题是,首先 find 命令列出 /tmp 下的所有文件,然后将该(巨大)列表作为参数传递给touch,这对于单次调用来说太多了。如果文件名包含空格、换行符、分号、& 符号、管道字符或类似字符,也会出现问题。

最好使用这个结构:

find /tmp -type f -exec touch -c '{}' +

find命令递归地列出/tmp.

-type f告诉 find 仅选择常规文件

-c选项可防止touch触摸创建不存在的文件。

看来您在示例中省略了一些逻辑,但如果您只想执行 200 次,您可以尝试以下操作:

#!/bin/bash

天号=1
测试 $dayNo -le 200 时
    查找 /tmp -type f -exec touch -c '{}' +
    睡眠 86000
    天号=$(表达式 1 + ${天号})
完毕

相关内容