【问题标题】:bash script improvement needed loops through dirs 12 hours old, deletes symbolic link inside and deletes dir需要改进 bash 脚本循环遍历 12 小时前的目录,删除内部的符号链接并删除目录
【发布时间】:2014-02-14 08:27:00
【问题描述】:

我已经完全编写了这个脚本,我希望得到一些更正,或者对我知道可能的更简单的版本有所了解......

我想遍历一个命名的目录并检查每个子目录是否包含任何 X 分钟前的子目录,如果是,则删除旧的子目录。每个符合条件的子目录将仅包含 1 个符号链接。

对于这个结构 /var/www/flash/avmin/{$usr_id}/{$timestamp}/{->symlink}

我想保留 /{$usr_id} 但如果 +12 小时前删除所有 /{$timestamp},我认为这意味着我需要在删除它之前清空它。

因为 /{$usr_id} 很可能会在创建 $timestamp 和符号链接时在同一个服务器实例中创建,所以我必须循环遍历每个 /{$usr_id} 子目录并从那里测试条件。

我会让这个脚本每 12 小时运行一次,Cron 以 root 身份运行,因此在 24 小时内所有符号链接都将被确保是干净的。

请注意,../{$usr_id} 中可能有多个 {$timestamp} 子目录,但每个子目录将仅包含 1 个符号链接,没有其他内容。

我感觉这可能是一两行没有 for...in 的代码,只需使用 find inside avmin using (-maxdepth 2) 和 X 小时(或 X 分钟)的时间条件,对吗???

#!/bin/bash

for i in /var/www/flash/avmin/*
do
    cd "$i"
    for xdir in "$i"
    do
        if [ "$xdir" type d -cmin +60 ]; then
            find . -maxdepth 2 -type L -cmin +60 -exec rm {} \
        "$xdir" -type d -cmin +60 -exec rm {}
    fi
        done
done
exit

我看到一个“类似的问题”让我有了一个想法here

【问题讨论】:

  • 你好。请编辑您的问题以首先明确说明您想要做什么:进入哪个目录,然后删除哪些符号链接? (那些超过 x 天?小时?秒?)。在你的脚本中,我现在觉得很奇怪: [ "$xdir" type d -cmin +60 ] 这没有任何意义,而且一旦它应该是,你就会“find”。而不是“find $xdir”,我也觉得这很奇怪......
  • 一点也不奇怪-只是脚本不好:)这就是我问的原因
  • 欢迎使用脚本 :) 我建议您从 linuxcommand.org 的全部内容开始(了解 linux 世界中的命令,然后了解 shell 脚本的基础知识)。然后,当您有问题时,请首先参考以下内容:mywiki.wooledge.org/BashFAQmywiki.wooledge.org/BashPitfalls。剩下的脚本/编程问题将很高兴在StackOverflow.com 中提出(但有关 unix/linux 命令的更多命令请参见:unix.stackexchange.comserverfault.com(+security.stackexchange.com 上的专家安全 Q)

标签: linux bash shell scripting cron


【解决方案1】:

我完全不确定我是否回答了正确的问题(请编辑您的问题以清楚说明您需要做什么,因为现在示例脚本没有什么意义...]

到目前为止我的猜测:

1) 对于 /var/www/flash/avmin/*/ 下的每个 dirs 1 级别,您想要查看,只有那些超过 60 分钟的目录

2) 那么您想在这些目录中删除所有超过 60 分钟的链接吗?

有了这些猜测:

#!/bin/bash

export NBMIN=60

#find all subdirs jsut underneath each /var/www/flash/avmin/*/ that are $NBMIN minutes old
for xdir in $(find /var/www/flash/avmin -type d -mindepth 2 -maxdepth 2 -cmin +${NBMIN} ) 
do
   #for those dirs, delete symlinks "just underneath", that are older than $NBMIN minutes
   find "$xdir" -mindepth 1 -maxdepth 1 -type L -cmin +${NBMIN} -exec echo rm '{}' \;
   #and then if there is nothing else in that dir, delete it:
   command rmdir "$xdir" #without -f and -r... will only remove "$i" directory if it's empty!
done

当然,这只有在每个目录和文件都是“普通”名称(即,不包含空格和其他奇怪的字符,如“换行符”或其他字符)时才有效...... Stephane 可能会弹出一个答案Zsh "**/" 细节 ;)

我不确定这是否是您想要的(请对其进行测试......并且只有在您 100% 确定它只列出你想看到的文件不见了!(例如,我不确定你只想查看超过 6000 万个目录?)

【讨论】:

  • 我正在使用你的脚本 - 我在我的服务器文件中按名称记下了你。以下是我发现对您的回答有帮助的内容:您向我展示了在每个语句中引用 $xdir 的正确方法,因为它确实是关键条件。我不可能想到使用最后一行(命令 rmdir "$xdir" )。现在我要学习..
  • 解释我为什么使用“command rmdir”:command something:在 bash 中,将绕过任何名为 something 的“别名”或函数,这样你就知道你运行了 something 二进制文件(或脚本)通过查看 $PATH... 由 shell 找到... 例如:alias ls="echo NO"; function ls { echo "AhAh" ; } ; ls ; \ls ; command ls : 'ls' 和 '\ls' 将运行该函数,并将显示 'Ahah'。命令 ls 将运行 /bin /ls 在当前目录,绕过函数和别名
  • 回答您的问题:'\;'是“逃避”';'因此外壳不会将其视为命令分隔符(; 是命令分隔符)...相反,由于它使用反斜杠进行转义,因此外壳将其视为普通字符,因此将其“发送”到find 命令,它使用它作为“-exec 分隔符的结尾”(即,知道 -exec 结束的位置)
  • 并且出于同样的原因,我还引用了 {},以便 shell 将它们视为简单字符,而不是 {} 命令组......当你开始时这一切都有意义阅读有关 shell 和 shell 脚本的信息 ^^。但是在 bash 中,您可以例如执行以下操作:cd /tmp ; pwd ; { cd / ; ls ; } >/dev/null ; pwd # 这将:进入 /tmp,然后显示它(pwd=打印工作目录),然后在当前外壳中执行 cd / ; ls 但将重定向所有此命令组输出进入 /dev/null (所以你不会看到它!),然后,因为它现在在“/”中,因为“cd /”是在当前 shell 中完成的,它将显示“/”。
  • 与 : () 比较,在子 shell 中运行命令:cd /tmp ; pwd ; ( cd / ; ls ; ) >/dev/null ; pwd :现在最后一个“pwd”将打印“/tmp”......因为整个“cd / ; ls”都发生了在一个子shell中,而不是在你当前的shell中,所以在当前的shell中你仍然在/tmp
猜你喜欢
  • 1970-01-01
  • 2010-09-17
  • 2019-08-26
  • 2011-04-06
  • 2018-03-12
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
  • 2011-05-11
相关资源
最近更新 更多