1

我经常调用以下脚本

清理.sh

#!/bin/bash
DEFAULT_LIMIT=10
INPUT=$1
PATTERN=$2
LIMIT=$3

if [ "$INPUT" == "" ] || [ "$PATTERN" == "" ]
then
        echo "usage: $0 INPUT PATTERN [LIMIT]"
        exit 1;
fi
if [ "$LIMIT" == "" ]
then
        LIMIT=$DEFAULT_LIMIT
fi

find /var/project/project1 -maxdepth 1 -type d -name "${INPUT}-${PATTERN}*" -printf '%T@ %p\n'|sort -nr|tail -n+$LIMIT|cut -f 2- -d " "|xargs -i rm -rf {}

所以这个应该删除最后一个但$LIMIT带有前缀的目录$INPUT-$PATTERNfrom/var/project/project1并且很少出乎意料地(尽管非常重要)它会删除除预期目录之外的目录 from /var/project/project1。知道为什么吗?cut 的行为是否为 2- 定义良好?我们可以在 f 和 field# 之间有空格吗?这不是故意编写的,而是一个错误,但不太确定这段代码是否是导致此意外删除的代码。

这很少能重现,因此不确定修复这个(cut -f2 -d " ")是否能解决我的问题

4

2 回答 2

3

您当前的实现将中断任何有空格的文件。这就是 的性质xargs,以及为什么除非使用 -0 (这在您当前的布局中不可能),否则它被认为是危险的。

举个例子,假设一个文件xargs被称为“foo bar”。xargs会像这样调用 rm :

rm -rf foo bar

它没有删除“foo bar”,而是删除了一个名为的文件foo和一个名为bar. 如果您将 cut 命令更改为-f2而不是-f2-,它仍会在带有空格的文件上中断,但只会删除foo.

这是一个处理所有可能文件名的示例:

#!/bin/bash
input=$1
pattern=$2
limit=${3:-10} # use 10 if $3 is not set

if [[ -z $input || -z $pattern ]]
then
        echo "usage: $0 INPUT PATTERN [LIMIT]"
        exit 1;
fi

dirs=()
while IFS= read -r -d '' latest # \0 is used as a delimiter, since it is not valid in a filename
do 
   dirs+=("$latest") # append files to the array in mtime sorted order, oldest first
done < <(find /var/project/project1 -maxdepth 1 -type d -name "${input}-${pattern}*" -printf '%T@ %p\0' | sort -zn)

dirs=("${dirs[@]#* }") # remove mtime from the elements
rm -rf "${dirs[@]:0:$limit}"
于 2012-08-30T02:43:39.593 回答
0

请注意,echo "one" | cut -f 2 -d " "即使我们要求第二个字段,它也会显示“一”。

那么,当您调用cut -f 2- -d " "并且只有一个字段时,您期望什么?如果没有,则添加该-s选项。

换句话说,改变

cut -f 2- -d " "

cut -s -f 2- -d " "

希望能帮助到你。

于 2012-08-30T04:05:21.643 回答