删除所有,但在bash最新的X文件 [英] Delete all but the most recent X files in bash

查看:121
本文介绍了删除所有,但在bash最新的X文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种简单的方法,在pretty标准的UNIX环境下使用bash,运行命令从目录中删除所有,但最新的X文件?

Is there a simple way, in a pretty standard UNIX environment with bash, to run a command to delete all but the most recent X files from a directory?

为了让更多的一个具体的例子中,假设一些cron作业写了一个文件(比如说,一个日志文件或焦油编了备份),以每小时目录。我想办法把另一cron作业运行这将删除该目录中的最旧的文件,直到有不足,比如,5。

To give a bit more of a concrete example, imagine some cron job writing out a file (say, a log file or a tar-ed up backup) to a directory every hour. I'd like a way to have another cron job running which would remove the oldest files in that directory until there are less than, say, 5.

和仅仅是明确的,但只有一个文件present,它应该永远不会被删除。

And just to be clear, there's only one file present, it should never be deleted.

推荐答案

与现有的答案的问题是:

The problems with the existing answers:


  • 无法处理文件名含有空格或换行符。

    • 在调用解决方案的情况下, RM 上一个不带引号命令替换直接( RM``... ),还有意想不到的通配的额外的风险。

    • inability to handle filenames with embedded spaces or newlines.
      • in the case of solutions that invoke rm directly on an unquoted command substitution (rm `...`), there's an added risk of unintended globbing.

      wnoise的回答解决了这些问题,但解决的办法是的 GNU 的特异性(和相当复杂的)。

      wnoise's answer addresses these issues, but the solution is GNU-specific (and quite complex).

      下面是一个务实, POSIX兼容的解决方案随只有一个警告:它不能处理文件名带有嵌入式的换行的 - 但我不T认为,对大多数人真实世界的关注。

      Here's a pragmatic, POSIX-compliant solution that comes with only one caveat: it cannot handle filenames with embedded newlines - but I don't consider that a real-world concern for most people.

      为了记录在案,这里是为什么它通常不是一个好主意来解析 LS的解释输出:http://mywiki.wooledge.org/ParsingLs

      For the record, here's the explanation for why it's generally not a good idea to parse ls output: http://mywiki.wooledge.org/ParsingLs

      ls -tp | grep -v '/$' | tail -n +6 | xargs -I {} rm -- {}
      

      以上就是低效,因为的xargs 已调用 RM 一次每个的文件名。结果
      平台的的xargs 可以让你解决这个问题:

      The above is inefficient, because xargs has to invoke rm once for each filename.
      Your platform's xargs may allow you to solve this problem:

      如果您有 GNU 的xargs ,使用 -d的'\\ n',使的xargs 考虑每个输入行一个单独的参数,但传递尽可能多的参数作为适合命令行的一次

      If you have GNU xargs, use -d '\n', which makes xargs consider each input line a separate argument, yet passes as many arguments as will fit on a command line at once:

      ls -tp | grep -v '/$' | tail -n +6 | xargs -d '\n' rm --
      

      如果您有 BSD 的xargs (包括 OS X ),你可以使用 -0 来处理 NUL 输入 - 分隔后,先换行转换为 NUL 为0x0 )字符,它也可以通过(典型值),所有文件名的一次的(也将与GNU <工作code>的xargs )

      If you have BSD xargs (including on OS X), you can use -0 to handle NUL-separated input, after first translating newlines to NUL (0x0) chars., which also passes (typically) all filenames at once (will also work with GNU xargs):

      ls -tp | grep -v '/$' | tail -n +6 | tr '\n' '\0' | xargs -0 rm --
      

      说明:


      • LS -tp 打印的排序文件系统项目的名称,他们是如何被最近修改,按降序排列(最近首次修改的项目)( -t ),印有一个尾随 / 来标记它们(目录 -p )。

      • 的grep -v'/ $'然后从打开的上市会淘汰目录,通过省略( -v )有一个尾随行 / / $ )。

        • 买者的:由于的符号链接指向一个目录的在技术上是不是本身就是一个目录,例如符号链接会的的排除

        • ls -tp prints the names of filesystem items sorted by how recently they were modified , in descending order (most recently modified items first) (-t), with directories printed with a trailing / to mark them as such (-p).
        • grep -v '/$' then weeds out directories from the resulting listing, by omitting (-v) lines that have a trailing / (/$).
          • Caveat: Since a symlink that points to a directory is technically not itself a directory, such symlinks will not be excluded.

          • xargs的-I {} RM - {} 定义占位符 {} 的再presents每输入行的作为一个整体的,所以 RM 然后为每个输入行调用一次,但与正确处理嵌入空格的文件名。

          • - 在所有情况下,确保这种情况发生下手任何文件名 - 是没有错的话选项的由 RM

          • xargs -I {} rm -- {} defines placeholder {} that represents each input line as a whole, so rm is then invoked once for each input line, but with filenames with embedded spaces handled correctly.
          • -- in all cases ensures that any filenames that happen to start with - aren't mistaken for options by rm.

          A 变异在原来的问题,的情况下匹配的文件需要处理的个别收集在一个shell阵列

          A variation on the original problem, in case the matching files need to be processed individually or collected in a shell array:

          # One by one, in a shell loop (POSIX-compliant):
          ls -tp | grep -v '/$' | tail -n +6 | while IFS= read -r f; do echo "$f"; done
          
          # One by one, but using a Bash process substitution (<(...), 
          # so that the variables inside the `while` loop remain in scope:
          while IFS= read -r f; do echo "$f"; done < <(ls -tp | grep -v '/$' | tail -n +6)
          
          # Collecting the matches in a Bash *array*:
          IFS=$'\n' read -d '' -ra files  < <(ls -tp | grep -v '/$' | tail -n +6)
          printf '%s\n' "${files[@]}" # print array elements
          

          这篇关于删除所有,但在bash最新的X文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆