Reputation: 9583
I have a range of files in the format namen.txt and I'd like to remove all but 3 whos n immediately precedes a selected file.
ie. if I input file24.txt I want to delete any file lower than file20.txt
The following works, but is there a simpler way? perhaps using find -name -delete
or similar?
file=file24.txt
num=$(sed 's/[^0-9]//g' <<< $file)
((num-=3))
while :
do
files=($(find $dir -name "*txt"))
count=${#files[@]}
if ((count < 1 ))
then
break
fi
rm file"$num".txt
((num--))
done
Upvotes: 1
Views: 433
Reputation: 7981
I think this might be one of the easiest ways of doing it:
shopt -s extglob
rm !(file21.txt|file22.txt|file23.txt)
Here's a simple function that does this in a more generic way:
function rmbut3() {
for ((n=0 ; n < $(($1 - 3)) ; n++))
do
rm file${n}.txt
done
}
rmbut3 24 # deletes files up to file20.txt
Upvotes: 1
Reputation: 753695
I'd probably do this with a Perl script:
#!/usr/bin/env perl
use strict;
use warnings;
for my $arg (@ARGV)
{
my($prefix, $number, $suffix) = ($arg =~ m/^ (\D+) (\d+) (\D.*) $/x);
foreach my $i (1..$number-4)
{
my $file = "$prefix$i$suffix";
unlink $file;
print "$file\n";
}
}
For each of the arguments specified on the command line, the name is split into 3 bits: a non-empty prefix of non-digits, a non-empty number of digits, and a suffix consisting of a non-digit followed by any sequence of characters (so file1.bz2
is split into file
, 1
and .bz2
). Then, for each number from 1 to 4 less than the given number, generate a file name from the prefix, the current number, and the suffix. With that file name, unlink the file and print the name. You can tweak it to remove only files that exist, or not report the names, or whatever. There's no fixed limit on the maximum number of files.
You could omit the unlink
and simply print the file names and send those to xargs rm -f
or an equivalent. You could ensure that the names were terminated with a null byte so that names with newlines could be handled correctly by GNU xargs
and the -0
option. Etc.
You could code this in pure Bash if you wished to, though the splitting into prefix, number, suffix will be messier than in Perl. I wouldn't use awk
for this, though it could probably be forced to do the job if you chose to make it do so.
Upvotes: 1
Reputation: 77095
Here is one way of doing it:
#!/bin/bash
# Grab the number from file passed to the script. $1 holds the that value
num="${1//[!0-9]}"
# To prevent from matching no files enable this shell option
shopt -s nullglob
# Iterate over the desired path where files are
for file in *; do
# Capture the number from file in loop
n=${file//[!0-9]}
# If file has no number and matches your criteria, delete the file
[[ ! -z $n ]] && (( n < num - 3)) && rm "$file"
done
Run it as:
./script.sh file24.txt
Upvotes: 1