2

I am trying to set-up an automatic way, for a given folder, to remove all its subfolders but the most recent created ones.

For instance, I would like to keep only the 3 most recent subfolders, and remove all the other ones.

Imagine the given folder:

/some/specific/folder
    /subfolder1
    /subfolder2
    /subfolder3
    /subfolder4
    /subfolder5
    /subfolder6
    /subfolder7
    /subfolder8
    /subfolder9
    /subfolder10

I would like to delete all subfolders but keep subfolder8, subfolder9 and subfolder10...

For now, I managed to list the files I would like to keep, but how to "reverse" it within a shell command?

cd /some/specific/folder/
ls -tr | head -3

# Gives the following result
subfolder8
subfolder9
subfolder10

# And I am looking for the following :
subfolder1
subfolder2
subfolder3
subfolder4
subfolder5
subfolder6
subfolder7

Any idea?

  • 2
    ls -tr | head -3 would give you the 3 oldest non-hidden files. – Stéphane Chazelas Sep 14 '16 at 15:10
5

If ls -tr | head -3 gives you the correct 3 folders to keep, then ls -tr | tail -n +4 will give you all the other folders (it skips the 3 first lines).

  • This will happily mix files and subdirectories. – Satō Katsura Sep 14 '16 at 16:37
  • Thanks, good to know. In my case I only have folders, but it's good to notice it! – Flo Schild Sep 14 '16 at 16:49
3

With zsh:

cd /some/specific/folder && echo rm -rf -- *(/n[1,-4])

Would remove all but the 3 last folders (/) in numerical (n) sorting order (where subfolder10 sorts after subfolder2), excluding hidden ones.

Remove the echo to actually perform the operation.

Note that creation time is not recorded on many systems, and when it is (like on recent Linux), there's not easy way to retrieve it. All you can rely on is the time of last modification (the date shown in the ls -l output).

To remove all but the last 3 most recently modified ones, still with zsh:

cd /some/specific/folder && echo rm -rf -- *(/Om[1,-4])

Om reverse-orders by modification time (from the oldest to the newest like ls -tr).

If you don't have or can't install zsh but are on a recent GNU system, you could do instead:

(export LC_ALL=C
cd /some/specific/folder &&
  find . ! -name . -prune -type d ! -name '.*' -printf '%T@\t%f\0' |
    sort -rnz |
    tail -zn +4 |
    cut -zf 2- |
    xargs -r0 echo rm -rf --)

For less recent GNU systems (-z has only been added recently to some of those utilities):

(export LC_ALL=C
cd /some/specific/folder &&
  find . ! -name . -prune -type d ! -name '.*' -printf '%T@\t%f\0' |
    tr '\n\0' '\0\n' |
    sort -rn |
    tail -n +4 |
    cut -f 2- |
    tr '\0\n' '\n\0' |
    xargs -r0 echo rm -rf --)

If none of the file names in the directory contain newlines, blanks or quotes or backslashes, you could also do:

cd /some/specific/folder &&
  ls -pt | grep '/$' | tail -n +4 | xargs echo rm -rf --

For a numerical sort like zsh's *(n), see also GNU ls -v option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.