Question: How do you delete all files in a directory except the newest 3?
Finding the newest 3 files is simple:
ls -t | head -3
As an extension to the answer by flohail. If you want to remove all folders except the newest three folders use the following:
find . -maxdepth 1 -mindepth 1 -type d -printf '%T@\t%p\n' |
sort -t $'\t' -g |
head -n -3 |
cut -d $'\t' -f 2- |
xargs rm -rf
The -mindepth 1
will ignore the parent folder and -maxdepth 1
subfolders.
Below worked for me: ( Cheers
The following looks a bit complicated, but is very cautious to be correct, even with unusual or intentionally malicious filenames. Unfortunately, it requires GNU tools:
count=0
while IFS= read -r -d ' ' && IFS= read -r -d '' filename; do
(( ++count > 3 )) && printf '%s\0' "$filename"
done < <(find . -maxdepth 1 -type f -printf '%T@ %P\0' | sort -g -z) \
| xargs -0 rm -f --
Explaining how this works:
<mtime> <filename><NUL>
for each file in the current directory.sort -g -z
does a general (floating-point, as opposed to integer) numeric sort based on the first column (times) with the lines separated by NULs.read
in the while
loop strips off the mtime (no longer needed after sort
is done).read
in the while
loop reads the filename (running until the NUL).xargs -0
then appends that filename into the argv list it's collecting to invoke rm
with.ls -t | tail -n +4 | xargs -I {} rm {}
If you want a 1 liner
ls -t | tail -n +4 | xargs -I {} rm {}
Michael Ballent's answer works best as
ls -t | tail -n +4 | xargs rm --
throw me error if I have less than 3 file
#!/bin/bash
if (( $# != 2 )); then
echo "Usage: $0 </path/to/top-level/dir> <num files to keep per dir>"
exit
fi
while IFS= read -r -d $'\0' dir; do
# Find the nth oldest file
nthOldest=$(find "$dir" -maxdepth 1 -type f -printf '%T@\0%p\n' | sort -t '\0' -rg \
| awk -F '\0' -v num="$2" 'NR==num+1{print $2}')
if [[ -f "$nthOldest" ]]; then
find "$dir" -maxdepth 1 -type f ! -newer "$nthOldest" -exec rm {} +
fi
done < <(find "$1" -type d -print0)
$ tree test/
test/
├── sub1
│ ├── sub1_0_days_old.txt
│ ├── sub1_1_days_old.txt
│ ├── sub1_2_days_old.txt
│ ├── sub1_3_days_old.txt
│ └── sub1\ 4\ days\ old\ with\ spaces.txt
├── sub2\ with\ spaces
│ ├── sub2_0_days_old.txt
│ ├── sub2_1_days_old.txt
│ ├── sub2_2_days_old.txt
│ └── sub2\ 3\ days\ old\ with\ spaces.txt
└── tld_0_days_old.txt
2 directories, 10 files
$ ./keepNewest.sh test/ 2
$ tree test/
test/
├── sub1
│ ├── sub1_0_days_old.txt
│ └── sub1_1_days_old.txt
├── sub2\ with\ spaces
│ ├── sub2_0_days_old.txt
│ └── sub2_1_days_old.txt
└── tld_0_days_old.txt
2 directories, 5 files