如何删除目录中具有特定扩展名的所有文件(最后 5 个除外)

如何删除目录中具有特定扩展名的所有文件(最后 5 个除外)

该目录包含具有不同扩展名的文件。我想删除除最后 5 个文件之外的所有扩展名为 .gz、zx、ext4 的文件。我可以列出所有这些文件

ls -l | grep '\.gz\|xz\|ext4$'

我可以只显示其中最旧的 5 个:

ls -l | grep '\.gz\|xz\|ext4$' | head -5

或者列出最后 5 个文件:

ls -l | grep '\.gz\|xz\|ext4$' | tail -5

但我不知道如何删除除上述命令中列出的这 5 个文件之外的所有文件。

答案1

如果通常的排序顺序没问题(即文件按日期命名),并且您的 shell 支持数组,则可以使用它们来避免使用时的常见注意事项ls:

F=(./*.{gz,xz,ext4})          # list files
G=("${F[@]:5}")               # pick all but the first five to another array
G=("${F[@]:0:${#F[@]}-5}")    # or pick all but the last five
rm -- "${G[@]}"               # remove them

zsh本身可以按日期排序,因此这会将匹配的文件抓取到一个数组中,并按修改时间排序

F=(./*.(gz|xz|ext4)(Om))

(Om)最新的放在最后,(om)最新的放在前面。)按上述方式处理数组。


当然,如果你需要按修改日期排序,就不能使用zsh知道你的文件名很好,一个简单的ls -t | tail -n +6就可以了。 tail -n +6从第六行开始打印,即跳过前五行。一开始我对此有一个偏差。)

使用 GNU ls,我认为我们可以要求它引用文件名来为 shell 创建合适的输入,然后用输出填充数组:

eval "F=($(ls -t --quoting-style=shell-always ./*.{xz,gz}))"

但这需要相信这一点,ls并且 shell 同意如何解释引号。

答案2

ls -1 | grep '\.gz$\|xz$\|ext4$' | tail -n +6 | xargs rm

注意事项:您的文件不应包含空格/引号。

set -f; set ./*.[gx]z ./*.ext4; [ "$#" -gt 5] && shift 5; rm -f "$@"

以下内容适用于任何类型的文件名:

td="`mktemp`" \
   find . -maxdepth 1 -type f \( -name \*.[gx]z -o -name \*.ext4 \) -exec sh -c '
      [ ! -s "$td" ] && [ "$#" -gt 5 ] && { shift 5; echo >> "$td"; }
      rm -f "$@"
   ' x {} +
rm "$td"

答案3

你快到了。

使用长选项格式指定所需的行数,然后将其取反。 (相反的逻辑可以与 一起使用tail)。

head --lines=3从头部打印三行

head --lines=-3从头部打印除最后三个之外的内容

head这是一个使用 a和一个名为的八行文件的示例f

$ cat f
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
$ head -3 f
line 1
line 2
line 3
$ head --lines=3 f
line 1
line 2
line 3
$ head --lines=-3 f
line 1
line 2
line 3
line 4
line 5

在开始删除文件之前检查这部分是否产生了您想要的内容。

长选项并不是严格必需的,但它没有必须向后兼容 tail 和 head 命令的演变的遗留问题,而且我发现它更容易记住。

head -n-3与长选项等效head --lines=-3 f

见下文

$ head -3 f #originally
line 1
line 2
line 3
$ head -n3 f #
line 1
line 2
line 3
$ head -n+3 f
line 1
line 2
line 3
$ head -n-3 f
line 1
line 2
line 3
line 4
line 5
$

答案4

以下命令将列出除最后 5 个文件之外的所有文件:

ls -l | grep '\.gz\|xz\|ext4$' | head -n `expr \`ls | grep '\.gz\|xz\|ext4$' | wc -l\` - 4`

您应该能够将其转换为命令来轻松删除文件。

相关内容