如何获取find的-exec中的basename?

时间:2013-08-13 01:23:19

标签: bash rm

我无法获得以下脚本(这是更大的备份脚本的一部分)才能正常工作:

BACKUPDIR=/BACKUP/db01/physical/incremental # Backups base directory
FULLBACKUPDIR=$BACKUPDIR/full # Full backups directory
INCRBACKUPDIR=$BACKUPDIR/incr # Incremental backups directory
KEEP=5 # Number of full backups (and its incrementals) to keep
...
FIRST_DELETE=`expr $KEEP + 1` # add one to the number of backups to keep, this will be the first deleted
FILE0=`ls -ltr $FULLBACKUPDIR | awk '{print $9}' | tail -$FIRST_DELETE | head -1` # search for the first backup to be deleted
...
find $FULLBACKUPDIR -maxdepth 1 -type d ! -newer $FULLBACKUPDIR/$FILE0 -execdir echo "removing: "$FULLBACKUPDIR/$(basename {}) \; -execdir bash -c 'rm -rf $FULLBACKUPDIR/$(basename {})' \; -execdir echo "removing: "$INCRBACKUPDIR/$(basename {}) \; -execdir bash -c 'rm -rf $INCRBACKUPDIR/$(basename {})' \;

所以这个查找工作正常,它本身会输出这样的东西:

/BACKUPS/db01/physical/incremental/full/2013-08-12_17-51-28
/BACKUPS/db01/physical/incremental/full/2013-08-12_17-51-28
/BACKUPS/db01/physical/incremental/full/2013-08-12_17-25-07

我想要的是-exec回显显示正在删除的内容的行,然后从两个目录中删除该文件夹。

我尝试了各种方法来获取基本名称,但似乎没有任何工作。我明白了:

removing: /BACKUPS/mysql/physical/incremental/full/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-51-28"
removing: /BACKUPS/mysql/physical/incremental/incr/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-51-28"
removing: /BACKUPS/mysql/physical/incremental/full/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-25-07"

当然文件夹不会被删除,因为它们不存在,只是因为-f选项而无声地失败。如果我删除-f,我会在每个rm上收到“无法找到”错误。

我如何做到这一点?由于备份和部分备份可能存储在不同的存储系统中,因此我真的需要能够获取文件夹名称以便在任何已知路径中使用。

2 个答案:

答案 0 :(得分:0)

首先运行$(basename {}),将removing: "$INCRBACKUPDIR/$(basename {})设为removing: "$INCRBACKUPDIR/{},然后替换为{}

绕过它的方法可能是将它传递给bash:

-exec echo "echo \"removing: \\\"$INCRBACKUPDIR/\$(basename {})\\\"\" | bash" \;

答案 1 :(得分:0)

这里有很多破碎。

  • 所有大写变量都是按惯例env变量,不应在脚本中使用。
  • 使用旧版反引号代替$()
  • 解析ls(!)
  • 的输出
  • 解析ls -l(!!!)
  • 的输出
  • 扩展已知包含没有完整引号的路径的变量。

所有绝对需要为了改善这一点,-exec bash正确,例如。

-execdir bash -c 'filepath="$1" ; base=$(basename "$filepath") ; echo use $filepath and $base here' -- {} \;

但是这样呢:

#!/usr/bin/env bash

backup_base=/BACKUP/db01/physical/incremental
full_backup="$backup_base"/full
incremental_backup="$backup_base"/incr
keep=5
rm=echo

let n=0
while IFS= read -r -d $'\0' line ; do
    file="${line#* }"
    if [[ $n -lt $keep ]] ; then
            let n=n+1
            continue
    fi
    base=$(basename "$file")
    echo "removing: $full_backup/$base"
    "$rm" -rf -- "$full_backup"/"$base"
    echo "removing: $incremental_backup/$base"
    "$rm" -rf -- "$incremental_backup"/"$base"
done < <(find "$full_backup" -maxdepth 1 -printf '%T@.%p\0' 2>/dev/null | sort -z -r -n -t. -k1,2)

直接在备份目录下迭代文件和目录,并跳过最新的5个。从与其余名称匹配的完整和增量目录文件中删除。

这是一个基本上安全的版本,当然除了定时攻击。

我已将rm定义为echo以避免意外删除; 一旦你确定它是正确的,就把它交换回rm进行实际删除。