我已经看到很多警告,反对文件名的危险,有趣的角色在shell脚本中造成严重破坏。
我已经搜索了SO并看到了xargs
和-exec rm -rf {} \;
的几十种变体,以及“不使用ls
编写脚本”而且我想出了我< em>认为是“安全”的。
find /path/to/dir -mindepth 1 -maxdepth 1 -type d -print0 | sort -z | head -z -n -10 | xargs -r0 rm -rf
我有一个以这种格式装满子目录的目录:
# find /srv/mywebsite/releases -mindepth 1 -maxdepth 1 -type d | sort
/srv/mywebsite/releases/2017-01-01T01:43:23Z
/srv/mywebsite/releases/2017-01-01T02:09:44Z
/srv/mywebsite/releases/2017-01-01T02:20:06Z
...
/srv/mywebsite/releases/2017-04-22T01:34:45Z
/srv/mywebsite/releases/2017-04-30T03:24:19Z
/srv/mywebsite/releases/2017-05-02T01:48:39Z
我想删除除最后10个之外的所有内容,按目录名称中的日期排序,不目录mod / create-time。这只是一个预防措施,以防其中一个目录被touch
编辑并且mtime / ctime不匹配。
我认为我上面的shell命令应该就是这样,但我只想仔细检查一下如果其中一个dirs包含*
或.
或者它将不会炸毁我的服务器东西。
答案 0 :(得分:3)
这是安全的,因为:
*
的名称不会产生额外的rm
参数。/path/to/dir
为前缀,因此我们不必担心将前导符号解释为选项。 (在确实有此问题的情况下,xargs -r0 rm -rf --
是合适的;对于POSIX utility syntax guideline #10,传递字符串--
可确保将所有后续参数解析为位置)。rm
的多个参数中生成单个名称结果。 (编写得不好的脚本通常会对换行做出类似的假设,但这种假设是没有根据的。)因为您依赖于以特定格式表示UTC时间戳的名称(以及新名称继续匹配该格式以便可以与旧名称进行适当比较),您可能需要添加适当的过滤器,使完整的命令类似于:
find /path/to/dir -mindepth 1 -maxdepth 1 -type d \
-regextype posix-extended \
-regex '.*/[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}Z$' \
-print0 | sort -z | head -z -n -10 | xargs -r0 rm -rf --
这些都不是特别可移植 - 原始代码和上述建议都要求对find
,sort
,head
进行非POSIX扩展, xargs
;并且在Windows文件系统(其中保留:
)上不允许使用命名约定 - 但如果您在UNIXy平台上运行现代GNU工具链,这对我来说很好。