LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 12-04-2010, 01:25 AM   #1
vbekker
Member
 
Registered: Aug 2010
Location: Brooklyn, NY
Distribution: CentOS
Posts: 38

Rep: Reputation: 0
Would like to delete all files in a directory except the 7 latest ones


Hi,
Here is how i am isolating the 7 latest files
Code:
ls -ltr | tail -7
is there a way to give that negated list to the rm command?
or should i be using the find command with an exec {}?
Thank YOu
 
Old 12-04-2010, 01:40 AM   #2
barriehie
Member
 
Registered: Nov 2010
Distribution: Debian Lenny
Posts: 136
Blog Entries: 1

Rep: Reputation: 23
Quote:
Originally Posted by vbekker View Post
Hi,
Here is how i am isolating the 7 latest files
Code:
ls -ltr | tail -7
is there a way to give that negated list to the rm command?
or should i be using the find command with an exec {}?
Thank YOu
Here's a way:
Code:
#
#  Leave 7 session files
#
# Specify the target directory and file names to operate on.
target_files=/home/barrie/.nautilus/saved-session-*

# Calculate the total number of files matching the target criteria. 
total_files=$(ls -t1 $target_files | wc --lines)

# Specify the number of files to retain.
retained_files=7

# If there are surplus files, delete them.
if [ $total_files -gt $retained_files ]
  then
  rm $(ls -t1 $target_files | tail --lines=$((total_files-retained_files)))
fi
 
Old 12-04-2010, 03:10 AM   #3
gd2shoe
Member
 
Registered: Jun 2004
Location: Northern CA
Distribution: Debian
Posts: 835

Rep: Reputation: 49
I don't think your rm line will work right. You should probably use xargs with the -d '\n' option. That will help when dealing with spaces in file names.

Additionally, directories included in $target_files cause things to go screwy. We don't know for sure that he's dealing with session information or log files yet. He might have errant subdirectories that need avoiding.

I suggest something closer to this:
Code:
#
#  Leave 7 newest files
#
# Specify the target directory and file names to operate on.
target_files=~/target_dir/*

#remove directories(etc) from target
target_files=$(ls -t1d --file-type $target_files | grep -v '[/=>@|]$')  #there's probably a better way

# Calculate the total number of files matching the target criteria. 
total_files=$(ls -t1 $target_files | wc --lines)

# Specify the number of files to retain.
retained_files=7

# If there are surplus files, delete them.
if [ $total_files -gt $retained_files ]
  then
  ls -t1d $target_files | tail --lines=$((total_files-retained_files)) | xargs -d '\n' rm
fi
(may still contain bugs)
 
Old 12-04-2010, 03:27 AM   #4
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371
Hi,

Assuming there are no directories present in the output (they won't be deleted, but an error will be shown), this is probably the simplest way:

Code:
ls -Qtr | tail -7 | xargs rm
(misread the original question.... Sorry!) See post #7

The -l isn't needed (it will only complicate things), the -Q puts double quotes around the found entries (takes care of spaces and the lot).

Hope this helps.

Last edited by druuna; 12-04-2010 at 04:16 AM. Reason: Misread the original question.
 
Old 12-04-2010, 03:33 AM   #5
gd2shoe
Member
 
Registered: Jun 2004
Location: Northern CA
Distribution: Debian
Posts: 835

Rep: Reputation: 49
Thanks for -Q. That's nifty.

Note, though, that he wants to delete all the files except the most recent 7. That's what the jumping through hoops and wc are about.

edit: also, that's not a -l, that's a -1. It's barriehie's way of making absolutely certain each file is on a separate line when it hits wc.

Last edited by gd2shoe; 12-04-2010 at 03:36 AM. Reason: addendum
 
Old 12-04-2010, 03:51 AM   #6
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,439

Rep: Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879
Here's 2 cents worth:
Code:
target_dir=~/target_dir

(( NUM_FILES = $(find $target_dir -maxdepth 1 -mindepth 1 -type f | wc -l) - 7 ))

if (( NUM_FILES > 0 ))
then
    find $target_dir -maxdepth 1 -mindepth 1 -type f -exec ls -rt {} \; 2> /dev/null | head -n $NUM_FILES | xargs rm
fi
Probably needs tweaking but you get the idea.
 
Old 12-04-2010, 04:14 AM   #7
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371
Hi again,

Sorry for the incorrect answer in post #4!

Here's a one-liner that should work:

Code:
ls -1Qtr | head -$(($(ls -1 | wc -l)-7)) | xargs rm
Hope this helps.

Last edited by druuna; 12-04-2010 at 04:16 AM.
 
Old 12-04-2010, 05:05 AM   #8
gd2shoe
Member
 
Registered: Jun 2004
Location: Northern CA
Distribution: Debian
Posts: 835

Rep: Reputation: 49
Neat. A little buggy, but very compact. (Fewer than 7 files or the presence of subdirectories cause problems.)

Here's my attempt without wc:
Code:
target=~/target/*
retained=2
ls -1tQd --file-type $target | grep -v '[/=>@|]$' | (while test $((retained--)) -ne 0; do read; done ; xargs -r rm)
I'd have preferred to use "head -$retained", but head consumes all input.

Of course, mine has its own drawbacks. Setting retained to anything other than an integer causes all files to be deleted.
 
Old 12-04-2010, 10:03 AM   #9
barriehie
Member
 
Registered: Nov 2010
Distribution: Debian Lenny
Posts: 136
Blog Entries: 1

Rep: Reputation: 23
In regards to the 7 latest files are they generated any way such that find can be used? Only asking because find may have fewer CLI contortions than using ls.
 
Old 12-04-2010, 10:07 AM   #10
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
I haven't read every word of every post in this thread, but wanted to point the OP to this other thread:
http://www.linuxquestions.org/questi...-files-839315/
where it appears that the OP there wanted to do the same (or a very similar) thing. Maybe you can learn something there that will help, and apply it here.

Last edited by GrapefruiTgirl; 12-04-2010 at 10:08 AM.
 
1 members found this post helpful.
Old 12-04-2010, 10:40 AM   #11
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,439

Rep: Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879Reputation: 1879
I like it Be interesting to see how the running times would be affected if you put the rm into your awk ... but nice all the same.
 
Old 12-04-2010, 10:46 AM   #12
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Quote:
Originally Posted by grail View Post
I like it ....
If you're referring to my little script - well, I suppose you should like it a little bit at least- it exists thanks to some code that you posted priorly somewhere, using similar `find -printf` functionality. So, thank you!
 
Old 12-04-2010, 01:14 PM   #13
vbekker
Member
 
Registered: Aug 2010
Location: Brooklyn, NY
Distribution: CentOS
Posts: 38

Original Poster
Rep: Reputation: 0
Thank you all very much for this....Just a follow up question.

Code:
tail +10 Output every line from line 10 onwards.
This is true in UNIX (on Solaris, korn shell), how would i achieve the same functionality in Linux bash?
If might be alot simpler to sort the list of files by time (ls -1t) and then use the tail +7 command to show all lines that are not the first 7 and do manipulation (rm) on those lines. Please correct me if i wrong.
Thank You
 
Old 12-04-2010, 04:02 PM   #14
vbekker
Member
 
Registered: Aug 2010
Location: Brooklyn, NY
Distribution: CentOS
Posts: 38

Original Poster
Rep: Reputation: 0
this might be the simplest solution, what do you think?
Code:
rm -rf $(ls -1t | tail -n +7)
 
Old 12-04-2010, 04:35 PM   #15
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Quote:
Originally Posted by vbekker View Post
this might be the simplest solution, what do you think?
Code:
rm -rf $(ls -1t | tail -n +7)
One problem with the above, is that filenames containing spaces cause problems. To demonstrate:
Code:
root@reactor: ls -1t
crap
hello there
root@reactor: echo rm -rf $(ls -1t)
rm -rf crap hello there
root@reactor:
So you see, `rm` will try to delete 3 files, 2 of which do not exist; the result: the file with spaces in the name, didn't get deleted.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Delete files in a directory - RM MDeFreitas Linux - Newbie 3 06-25-2010 07:00 AM
sort files inside a directory and sub-directories by latest created walidaly Linux - Software 8 07-25-2009 02:45 PM
Delete Files in directory villumanati Linux - General 7 12-30-2008 01:18 PM
How to delete once whole files in a remote directory? backpacker Linux - Networking 1 03-10-2006 05:04 AM
How can I delete a directory and its files? OrganicX Linux - General 6 09-01-2002 04:25 AM


All times are GMT -5. The time now is 10:22 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration