Shell script to count files, then remove oldest files

后端 未结 11 2215
眼角桃花
眼角桃花 2021-01-30 05:29

I am new to shell scripting, so I need some help here. I have a directory that fills up with backups. If I have more than 10 backup files, I would like to remove the oldest fi

相关标签:
11条回答
  • 2021-01-30 05:49
    stat -c "%Y %n" * | sort -rn | head -n +10 | \
            cut -d ' ' -f 1 --complement | xargs -d '\n' rm
    

    Breakdown: Get last-modified times for each file (in the format "time filename"), sort them from oldest to newest, keep all but the last ten entries, and then keep all but the first field (keep only the filename portion).

    Edit: Using cut instead of awk since the latter is not always available

    Edit 2: Now handles filenames with spaces

    0 讨论(0)
  • 2021-01-30 05:50

    On a very limited chroot environment, we had only a couple of programs available to achieve what was initially asked. We solved it that way:

    MIN_FILES=5
    FILE_COUNT=$(ls -l | grep -c ^d )
    
    
    if [ $MIN_FILES -lt $FILE_COUNT  ]; then
      while [ $MIN_FILES -lt $FILE_COUNT ]; do
        FILE_COUNT=$[$FILE_COUNT-1]
        FILE_TO_DEL=$(ls -t | tail -n1)
        # be careful with this one
        rm -rf "$FILE_TO_DEL"
      done
    fi
    

    Explanation:

    • FILE_COUNT=$(ls -l | grep -c ^d ) counts all files in the current folder. Instead of grep we could use also wc -l but wc was not installed on that host.
    • FILE_COUNT=$[$FILE_COUNT-1] update the current $FILE_COUNT
    • FILE_TO_DEL=$(ls -t | tail -n1) Save the oldest file name in the $FILE_TO_DEL variable. tail -n1 returns the last element in the list.
    0 讨论(0)
  • 2021-01-30 05:51

    Try this:

    ls -t | sed -e '1,10d' | xargs -d '\n' rm
    

    This should handle all characters (except newlines) in a file name.

    What's going on here?

    • ls -t lists all files in the current directory in decreasing order of modification time. Ie, the most recently modified files are first, one file name per line.
    • sed -e '1,10d' deletes the first 10 lines, ie, the 10 newest files. I use this instead of tail because I can never remember whether I need tail -n +10 or tail -n +11.
    • xargs -d '\n' rm collects each input line (without the terminating newline) and passes each line as an argument to rm.

    As with anything of this sort, please experiment in a safe place.

    0 讨论(0)
  • 2021-01-30 05:53

    The proper way to do this type of thing is with logrotate.

    0 讨论(0)
  • 2021-01-30 05:55

    I just found this topic and the solution from mikecolley helped me in a first step. As I needed a solution for a single line homematic (raspberrymatic) script, I ran into a problem that this command only gave me the fileames and not the whole path which is needed for "rm". My used CUxD Exec command can not start in a selected folder.

    So here is my solution:

    ls -A1t $(find /media/usb0/backup/ -type f -name homematic-raspi*.sbk) | tail -n +11 | xargs rm
    

    Explaining:

    • find /media/usb0/backup/ -type f -name homematic-raspi*.sbk searching only files -type f whiche are named like -name homematic-raspi*.sbk (case sensitive) or use -iname (case insensitive) in folder /media/usb0/backup/
    • ls -A1t $(...) list the files given by find without files starting with "." or ".." -A sorted by mtime -t and with a return of only one column -1
    • tail -n +11 return of only the last 10 -n +11 lines for following rm
    • xargs rm and finally remove the raiming files in the list

    Maybe this helps others from longer searching and makes the solution more flexible.

    0 讨论(0)
提交回复
热议问题