On Mon, Jan 12, 2009 at 16:59, Harry Putnam <rea...@newsguy.com> wrote: > I want to do something like this but with perl: > > rm -f $(ls -lt|sed -n '6,$p') > > so that the five newest files are always left. > > Is there some short way to get that effect in perl? > > Or do I have to analyze each file with stat or something? snip
In the end, someone has to stat each file, but you should be able to get what you want like this: my @files = map { $_->[1] } sort { $b->[0] <=> $a->[0] } map { -f $_ ? [-M _, $_] : () } <*>; pop @files for 1 .. 5; #some would use splice here for my $file (@files) { unlink $file or warn "could not remove $file: $!"; } The first part is a Schwartzian Transform. It is used because we don't want to have to keep stat'ing the files during the sort. So we 1. take the list of files in the current directory (<*>) 2. create a list of arrayrefs that contain the relative age of the each regular file and its file name (map { -f $_ ? [-M _, $_] : () }) 3. sort on the relative ages of the files (sort { $b->[0] <=> $a->[0] }) 4. and, finally, recover only the file names It is important to note that the _ is not a typo. It is a special filehandle that refers to the last stat'ed file. There is no reason to call stat a second time to get the relative age of the file since we know it from the first call to -f (the file test operators are just fancy stat calls). For more info read about the stat function*, the filetest operators**, and filetest pragma***. If you are not already familiar with the map**** and sort***** functions then you might want to read about them as well. Sort is fairly obvious, but map can take some getting used to. Its function is to take a list and return a transformed list. An easy example would be to find all of the squares of 1 through 5: my @squares = map { $_ * $_ } 1 .. 5; #will be (1, 4, 9, 16, 25) You can make a longer list than the input by producing a list inside the map: my %squares = map { $_, $_ * $_ } 1 .. 5; #will be 1, 1, 2, 4, 3, 9, 4, 16, 5, 25 You can also produce a smaller list by producing an empty list when you want to discard an item: my @dirs = map { -d $_ ? $_ : () } <*>; In this specific case we can use map's cousin grep******: my @dirs = grep { -d $_ } <*>; * http://perldoc.perl.org/functions/stat.html ** http://perldoc.perl.org/functions/-X.html *** http://perldoc.perl.org/filetest.html **** http://perldoc.perl.org/functions/map.html ***** http://perldoc.perl.org/functions/sort.html ****** http://perldoc.perl.org/functions/grep.html -- Chas. Owens wonkden.net The most important skill a programmer can have is the ability to read. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/