删除最旧的文件


9

我正在尝试从目录中删除旧文件,仅保留3个最新文件。

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

条件语句有问题。

Answers:


9

如果要循环播放文件,请不要使用ls *。tl; dr在很多情况下,您最终将删除错误的文件,甚至所有文件。

就是说,不幸的是,在Bash中这是一件棘手的事情。在一个 甚至更大find_date_sorted重复问题上,有一个有效的答案,您可以稍作修改即可使用:

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

*不冒犯-我ls以前也使用过。但这确实不安全。

编辑:单元测试的find_date_sorted功能。


我第二部分关于不解析ls。脚本也很整洁,但我认为可以在一个衬里完成,让我检查一下...
rahmu 2012年

好吧,您始终可以将Bash代码压缩为单一
格式

2
如果我无情地从@ Peter.O窃取了一个主意,请尝试((++counter>3))进行测试。非常简洁。至于单行代码:如果出于简洁考虑,请将代码包装在函数中,则不必担心。
Sorpigal'4

@Sorpigal整洁的快捷方式
l0b0 2012年

5

要使用zsh glob删除除3个最新文件以外的所有文件,可以使用Om(大写O)将文件从最旧到最新进行排序,并使用下标捕获所需的文件。

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

其他例子:

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])

5

到目前为止,最简单的方法是使用zsh及其glob限定符Om按年龄减小(即最老的优先)排序并[1,3]仅保留前三个匹配项。

rm ./*(Om[1,3])

有关更多示例,另请参见如何在zsh中过滤glob

并请注意l0b0的建议:如果文件名包含shell特殊字符,则代码将严重损坏


哇哇,这真的是一站式的完整解决方案吗?
MetaGuru 2012年


1

您可以使用以下功能来获取目录中的最新文件:

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

通过在每次迭代后挤出最新文件,为它提供不同的文件集。

提示:如果将初始文件集保存在名为“ $ {files [@]}”的数组中,则unset 'files[index]'在下一次迭代之前保存找到的最新文件的索引。

用法: newest_in [set of files/directories]

样本输出:

[rany$] newest_in ./*
foo.txt
[rany$]

-1

首先,该-R选项用于递归,这可能不是您想要的-它将也在所有子目录中搜索。其次,<运算符(当不被视为重定向时)用于字符串比较。你可能想要-lt。尝试:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

但我会在这里使用find:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]

如果一个或多个文件名包含“ $ \ n”,则两者都将失败。
Rany Albeg Wein

-1

我知道解析是一种罪过ls,但是这又是怎么回事:

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

快速测试5个空文件:

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5

这将失败有两个原因-解析ls输出并以错误的方式使用findxargs。如果结合使用findxargs我建议您使用finds -print0和相应的xargss -O选项。阅读有关使用查找的更多信息。您可能还想看看并了解为什么解析ls非常糟糕。
Rany Albeg Wein

-2

我认为这是一句话:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"

ls是用于交互式查看文件信息的工具。它的输出是为人类格式化的,将导致脚本中的错误。使用glob或find代替。了解原因:mywiki.wooledge.org/ParsingLs
Rany Albeg Wein

-2

这是一种解决方案:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)

1
@bakbak ls是用于交互式查看文件信息的工具。它的输出是为人类格式化的,将导致脚本中的错误。看这里了解原因。具体地说,是关于您的答案-如果一个或多个文件包含$'\ n'字符,则此答案将中断。另外,命令替换(即$(...))缺少双引号,这引出了另一个重要的主题-分
Rany Albeg Wein
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.