2

I am trying to remove files within a bash script.

I can list the latest file with:

ls | grep core | tail -n 1

and rename it like keep-core-2994-xyz.bin, then remove the rest with:

rm -f core-*

and then rename the latest to the original. In this way, I can keep the latest file and remove the rest. This works fine for this scenario:

-rw-------  1 root root  47M Sep  3  2017 core-2994-xyz.bin
-rw-------  1 root root  47M Sep  3  2017 core-3012-xyz.bin
-rw-------  1 root root  79M Sep  3  2017 core-3106-xyz.bin

However, this one: core-10000-xyz.bin causes trouble:

-rw-r--r--  1 root root  55M Sep  3  2017 core-10000-xyz.bin
-rw-------  1 root root  47M Sep  3  2017 core-3012-xyz.bin
-rw-------  1 root root  79M Sep  3  2017 core-3106-xyz.bin

... because this time, I need to keep the one I want with head, not with tail.

Is there any effective way to remove files except the latest one which were created by this order? (Here, core-3012-xyz.bin)

The file timestamps are unreliable; this is an embedded device and timestamps can change due to the internet connection, so I can't list them by timestamp.

This is an embedded device and I don't want to compile it with zsh; I'd like a bash-only solution, please.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
obayhan
  • 139

2 Answers2

4

With zsh:

rm -f -- *core*(n[1,-2])

Where the n glob qualifier turns on numericglobsort for that one glob expansion and [1,-2] selects the first to second last.

Or:

rm -f core-<1-4294967295>-xyz.bin(n.[1,-2])

If you want to make it more specific, where <1-2147483647> matches on sequences of digits that represent numbers in the range of valid pid numbers and the . qualifier restricts the expansion to regular files only.

Note that core-bar-123 would sort before core-bar-1000 but also before core-foo-1. The numeric sort is used when it comes to comparing numbers when the part leading up to them is the same. Here core-bar sorts before core-foo. Adding numbers to either won't change that.

To only consider the numbers when sorting, you could do something like:

extract_numbers() {
  set -o localoptions -o extendedglob
  REPLY=${${${REPLY//[^0-9]##/-}#-}%-}
}
rm -f --  *<->*(.no+extract_numbers[1,-2])

Where extract_numbers converts some123file5123with3numbers to 123-5123-3 which is then used for numeric ordering.

  • I like this a lot, but to be fair, the question has a [tag:bash] tag! – Marcus Müller May 16 '22 at 15:41
  • 1
    @MarcusMüller, sure. In bash, just do zsh -c 'that code' but why would anyone still use bash in this day and age :-b. In anycase, the answer would be useful to users landing here with similar requirements and not being limited to using bash – Stéphane Chazelas May 16 '22 at 15:46
  • Somehow, I do agree ;) – Marcus Müller May 16 '22 at 15:46
  • @StéphaneChazelas because as i wrote in question this is an embedded device and there is no reason to compile it together with zsh and believe me this is our last concern. – obayhan May 21 '22 at 22:26
0

Oh i found the solution.

ls -v | grep core | tail -n 1

will do the trick.

Reference:

List files sorted numerically

obayhan
  • 139
  • 1
    I'm sorry I've downvoted this, but: *Never* parse ls output. For example, this all breaks when a file has a newline in its name – which is a perfectly legal character. So, not really a solution. – Marcus Müller May 16 '22 at 15:42
  • also note that as Stéphane has pointed out, you could at least restrict your ls to only look into files that are called core-* to begin with. – Marcus Müller May 16 '22 at 15:44
  • 1
    But: you've linked to a good resource, but you focused on the answer producing output meant for human consumption, not for computer consumption. This answer uses the same "listing" method that Stéphane uses in their answer here. However, the "hard" part is selecting only the right file, and that's what's missing. – Marcus Müller May 16 '22 at 15:47
  • Your attempt @obayhan is incomplete, it's not going to delete anything. – tansy May 16 '22 at 21:11
  • $ ls -v -1 core-* | tail -n 1 | xargs rm -f – tansy May 16 '22 at 21:12
  • 1
    @MarcusMüller these are dump output files controlled by us, they don't have a chance get an empty or non-alphanumeric string in their names.So there is no reason not to parse "ls output" (: + this was an example, in real system dumps can get prefixes like xyz-core-1234, thats the reason of the grep. + i can guarantee there is anything else in there containing "core" Anyway thanks for the reminders to produce a "common" answer but my problem is not common.

    However they are unrelated to my question.

    As i said it is an embedded linux and i have all control over that directory.

    – obayhan May 21 '22 at 22:38
  • 1
    @MarcusMüller so please dont think it is an uncontrolled Desktop – obayhan May 21 '22 at 22:40
  • 1
    @tansy please read the question carefully – obayhan May 21 '22 at 22:40