Trying to delete all but most recent 2 files in su

2019-04-11 21:08发布

问题:

I'm creating a cron that cleans subdirectories (first child only) of a specified folder of all but the most recent two files but running into issues.

These are my attempts:

find ./ -type d -exec rm -f $(ls -1t ./ | tail -n +4);
find . -maxdepth 2 -type f -printf '%T@ %p\0' | sort -r -z -n | awk 'BEGIN { RS="\0"; ORS="\0"; FS="" } NR > 5 { sub("^[0-9]*(.[0-9]*)? ", ""); print }' | xargs -0 rm -f

I also tried to create an array of files with the intention of going through the total minus 2, but the array was not populating with all files:

while read -rd ''; do      x+=("${REPLY#* }");  done < <(find . -maxdepth 2 -printf '%T@ %p\0' | sort -r -z -n )

Could someone please give me a hand and explain how they have done?

回答1:

Unlike the existing answer, this one NUL-delimits the output from find, and is thus safe for filenames with absolutely any legal character -- a set which includes newlines:

delete_all_but_last() {
  local count=$1
  local dir=${2:-.}
  [[ $dir = -* ]] && dir=./$dir
  while IFS='' read -r -d '' entry; do
    if ((--count < 0)); then
      filename=${entry#*$'\t'}
      rm -- "$filename"
    fi
  done < <(find "$dir" \
             -mindepth 1 \
             -maxdepth 1 \
             -type f \
             -printf '%T@\t%P\0' \
           | sort -rnz)
}

# example uses:
delete_all_but_last 5
delete_all_but_last 10 /tmp

Note that it requires GNU find and GNU sort. (The existing answer also requires GNU find).



回答2:

This lists all but the most recent two files:

find -type f -printf '%T@ %P\n' | sort -n | cut -d' ' -f2- | head -n -2 

Explanation:

  • -type f list only files
  • -printf '%C@ %P\n'
    • %T@ show file's last modification time in seconds since 1970.
    • %P show the file name
  • | sort -n do a numeric sort
  • | cut -d' ' -f2- drop the seconds form output, leave only the filename
  • | head -n -2 show all but the last two lines

So to remove all these files just append pipe it through xargs rm or xargs rm -f:

find -type f -printf '%T@ %P\n' | sort -n | cut -d' ' -f2- | head -n -2 | xargs rm


回答3:

I just hit the same problem and that's how I solved it:

#!/bin/bash

# you need to give full path to directory in which you have subdirectories
dir=`find ~/zzz/ -mindepth 1 -maxdepth 1 -type d`

for x in $dir; do
        cd $x
        ls -t |tail -n +3 | xargs rm --
done

Explanation:

  • with tail -n +number you decide how many files you leave in subdirectories