我有以下路径:
/dir1/dir2/
在此路径中,我有以下目录,其中包含各种(不相关的)应用程序碎屑:
follower1234 1-Dec-2018
follower3456 2-Dec-2018
follower4567 3-Dec-2018
follower7890 9-Jan-2019
follower8901 10-Jan-2019
leader8765 4-Dec-2018
bystander6789 5-Dec-2018
假设今天是 2019 年 1 月 10 日。
假设可以有任意数量的followerXXXX
,leaderXXXX
和bystanderXXXX
目录。
我想要的是删除所有followerXXXX
目录,但最新followerXXX
目录除外,这些目录超过两周。
现在我可以删除所有早于特定日期的目录。但这不是我的问题。我正在添加两个附加参数。
在这种情况下,我想删除:
follower1234 1-Dec-2018
follower3456 2-Dec-2018
follower4567 3-Dec-2018
但不是
follower7890 9-Jan-2019
follower8901 10-Jan-2019
leader8765 4-Dec-2018
bystander6789 5-Dec-2018
即我想删除文件
(a) 匹配模式
(b) 两周以上
(c) 不是匹配模式的最新目录(即保留最后一个)
我的问题是:如何删除超过 2 周的目录中的所有目录,除了与文件模式匹配的最新目录?
介绍
问题已修改。
我的第一个替代方案(oneliner)与新规范不匹配,但将最新目录保存在足以删除(超过 14 天)的目录中。
我做了第二个选择,(shellscript)使用
@ 自 1970 年 1 月 1 日 00:00 GMT 以来的秒数,带有小数部分。
并减去对应于 14 天的秒数,以
seclim
获得排序后的目录列表中“秒数限制”的时间戳。1. 单线
以前的答案很干净,很好,但它们不保留最新的
follower
目录。以下命令行将执行此操作(并且可以管理带有空格的名称,但带有换行符的名称会产生问题),在这个目录结构上测试,
像这样,
所以
follower9
被排除在外,因为它是最新的follower
目录(有名称的目录,不以follower
(开头leader1
,leader2
并且2
不在游戏中)。现在我们添加时间标准,
-mtime +14
并进行另一次“试运行”以检查它是否正常工作,当我们将目录更改为存在真实follower
目录的位置时,最后我们删除
echo
并有一个可以做我们想做的命令行,find
在当前目录中,名称以 开头的目录,follower
自 14 天前以来未修改。head -n -1
会排除最新的follower
目录。xargs
作为参数传递rm -r
,以删除我们要删除的目录。2. 脚本
我做了第二个选择,(shellscript)使用
它也有两种选择,
-n
空跑-v
冗长的我根据 OP 的要求修改了 shellscript:在单引号中输入模式作为参数,例如“follower*”。
我建议 shellscript 的名称是
prune-dirs
因为它现在更通用(不再只是prune-followers
修剪目录follower*
)。建议您第一次使用这两个选项运行 shellscript,以便“查看”您将做什么,当它看起来正确时,删除
-n
以使 shellscript 删除足够旧的目录以删除。因此,让我们调用它prune-dirs
并使其可执行。follower
子目录的目录prune-dirs
并使用两个选项运行
-v -n
测试
我
prune-dirs
在具有以下子目录的目录中进行了测试,如find
用法
运行
-v -n
(详细的试运行)具有更一般模式的详细试运行
不带任何选项运行(删除目录的真实案例)
运行
-v
“再试一次”shellscript 没有列出“高于”“limit-in-seconds”的目录,并且没有为命令行列出任何文件
rm -r
,因此工作已经完成(这是正确的结果)。但是如果你几天后再次运行 shellscript,一些新目录可能会在“limit-in-seconds”之上找到并被删除。补充罗文的答案。您可以通过目录的路径更改点
With
zsh
:(remove
echo
when happy)<->
any sequence of decimal digits (a short form of<1-20>
be without bound).(){code} args
: anonymous function which here stores its number of arguments in$n
.(/omm+13)
: glob qualifier/
: only select files of type directory (equivalent offind
's-type d
)m+13
: files whose age in whole days is strictly greater than 13 days, so files that are 14 days old or older (equivalent offind
's-mtime +13
).om
: order by modification time (likels -t
younger files first)Note that it's dangerous to rely on directory modification time. directories are modified when files are added, removed or renamed in them (or when they're
touch
ed). Since those directories are numbered, you may want to rely on that numbering instead, so replaceom
withnOn
(n
umericallyO
rder in reverse (capitalO
) byn
ame).To have the pattern in a variable, replace
follower<->
with$~pattern
and setpattern='follower<->'
or any other value.当我需要删除与时间相关的文件或目录时,我会使用
find
.在删除任何内容之前,您可以运行该命令几次,看看它是否找到了您想要的所有内容。
如果它符合您的所有条件,您可以
-exec rm -r {} +
在其后面添加:我们在
-exec
这里使用的原因是,-delete
如果目录不为空,将无法正常工作。查看
man find
更多指导。几个解决方案:
1. 基于 GNU
find
:该脚本的调用方式如下:
照原样,它会给你一个空运行。
echo
在最后一个操作中删除-exec
以使其实际删除目录。它会:
-mtime
开头的值${patt}
对于每个:-exec
)找到的目录不是与名称模式匹配的最后一个目录,按版本升序排序(-V
)(例如,follower100
放在 之后follower2
);如果 test ([
) 失败,find
则跳到下一个循环并且不执行后面的动作;-exec
)。在这里,我假设按名称按字典顺序对目录进行排序和按修改日期对目录进行排序之间是等价的。如果您的最新目录是根据其名称定义的,则可以。
相反,如果您的最新目录是最近修改时间的目录,我们必须将
-exec ...
上面代码中的第一个替换为这个:在内部
find
,我们找到与名称模式匹配的所有目录,打印它们自 Epoch 以来的修改时间列表(以秒为单位),去掉小数部分,排序,取最后一个并检查它是否不等于当前的外部的结果find
。请注意,使用此过滤器,如果所有匹配的目录都超过 14 天并且修改时间完全相同,则不会删除它们。
笔记:
-maxdepth 1
不严格要求将搜索限制为当前目录 ( ) 的内容。You may want to tell
sort
how to order things, e.g. addingexport LC_ALL=C
at the beginning of the script (refer to this answer to 'What does "LC_ALL=C" do?' about the issues you may have when sorting, depending on your localization settings).Note that, using
-mtime +14
, files that have been modified between 14 and 15 days ago are skipped even if their modification time is technically older than 14*24 hours from now (refer toman find
for details; specifically, the description of-atime n
).It will work even when names contain spaces, newlines, uncommon and non-printable characters.
Compatibility: the flip side is that it is not portable: some features used here, notably
find
's-maxdepth
,-print0
and-printf
, thestat
command, the-V
option tosort
and the-z
option tosort
andtail
(and I am possibly forgetting some more), are not specified in POSIX.2. Based on shell features
This script, too, is meant to be invoked as
Again, it will give you a dry run until you remove
echo
fromecho rm -rf -- "${dirs[$i]}"
.It will:
Notes:
It will target directories older then 14 days from now (unlike
find
). Thus, these two solutions are not strictly equivalent.Also, if all the matching directories are older than the threshold and have all the same modification time, it will delete all but one of them - randomly chosen.
Names with uncommon characters are ok, including newlines and non printable ones.
Compatibility: even this solution relies on some non POSIX features: namely,
stat
and the%s
date
format. Ah, and arrays, apparently...