5

I untarred something into a directory that already contained a lot of things. I wanted to untar into a separate directory instead. Now there are too many files to distinguish between. However the files that I have untarred have been created just now (right ?) and the original files haven’t been modified for long (at least a day). Is there a way to delete just these untarred files based on their creation information ?

tchrist
  • 78,834
  • 30
  • 123
  • 180
AnkurVj
  • 7,958
  • 10
  • 43
  • 55

4 Answers4

7

Tar usually restores file timestamps, so filtering by time is not likely to work.

If you still have the tar file, you can use it to delete what you unpacked with something like:

tar tf file.tar --quoting-style=shell-always |xargs rm -i

The above will work in most cases, but not all (filenames that have a carriage return in them will break it), so be careful.

You could remove the directories by adding -r to that, but it's probably safer to just remove the toplevel directories manually.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 2
    It's really easy to make it work with spaces in the filenames, and that would be a much better answer. – Omnifarious Oct 01 '11 at 10:31
  • @omnifa how to make this work with spaces ? to remove the directories extracted, should I also include -R after rm ? – AnkurVj Oct 01 '11 at 10:40
  • @AnkurVj: Unfortunately there is not actually a way to make tar give you a null character separated list of filenames, which is quite disappointing. And yes, there should be a `-r` after the `rm`. Since Mat isn't updating the answer, I'll put in my own. – Omnifarious Oct 01 '11 at 10:46
  • @Omnifarious: I disagree about the "easy" part in your first comment. Sure it's doable, but I'm not going to write a script-that-safely-deletes-files-with-random-chars-in-them. They are tricky to do correctly for all cases. Adding `-r` just increases the damage caused by unforeseen characters. Unless there are hundreds of toplevel directories in that archive, I'd go manual on them. – Mat Oct 01 '11 at 10:54
  • @Mat: Yes, that does make sense about the `-r`. But I solved the other problem in my answer, and it's not actually that complicated. – Omnifarious Oct 01 '11 at 11:13
  • `tar` needs a `--quoting-style=null` option. Also, I added a method based on `--quoting-style` that will work on any filename, even if it has a newline. But I still think your answer is better because of it's simplicity. – Omnifarious Oct 01 '11 at 17:46
  • You can handle files and directories in one pass with: tar -tf ../test/bob.tar --quoting-style=shell-always | sed -e "s/^\(.*\/\)'$/rmdir \1'/; t; s/^\(.*\)$/rm \1/;" | sort | bash You can see what is going to happen leave off the pipe to 'bash' tar -tf ../test/bob.tar --quoting-style=shell-always | sed -e "s/^\(.*\/\)'$/rmdir \1'/; t; s/^\(.*\)$/rm \1/;" | sort – G. Allen Morris III May 04 '14 at 18:31
3

find . -mtime -1 -type f | xargs rm

but test first with

find . -mtime -1 -type f | xargs echo

Artis
  • 283
  • 2
  • 9
  • 2
    This would be good except for two things. First, **always** use `-print0` and `xargs -0`. You do not want random space characters in filenames to cause you problems. Secondly, `tar` restores timestamps, so you can't actually use mtime here. Perhaps atime, maybe, if your filesystem has been configured to update it. – Omnifarious Oct 01 '11 at 10:30
  • Also, note e.g. find -mmin -10 for files modified in the last ten minutes – sehe Oct 01 '11 at 10:43
1

There are several different answers to this question in order of increasing complexity.

First, if this is a one off, and in this particular instance you are absolutely sure that there are no weird characters in your filenames (spaces are OK, but not tabs, newlines or other control characters, nor unicode characters) this will work:

tar -tf file.tar | egrep '^(\./)?[^/]+(/)?$' | egrep -v '^\./$' | tr '\n' '\0' | xargs -0 rm -r

All that egrepping is to skip out on all the subdirectories of the subdirectories.

Another way to do this that works with funky filenames is this:

mkdir foodir
cd foodir
tar -xf ../file.tar
for file in *; do rm -rf ../"$file"; done

That will create a directory in which your archive has been expanded, but it sounds like you wanted that already anyway. It also will not handle any files who's names start with ..

To make that method work with files that start with ., do this:

mkdir foodir
cd foodir
tar -xf ../file.tar
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 sh -c 'for file in "$@"; do rm -rf ../"$file"; done' junk

Lastly, taking from Mat's answer, you can do this and it will work for any filename and not require you to untar the directory again:

tar -tf file.tar | egrep '^(\./)?[^/]+(/)?$' | grep -v '^\./$' | tr '\n' '\0' | xargs -0 bash -c 'for fname in "$@"; do fname="$(echo -ne "$fname")"; echo -n "$fname"; echo -ne "\0"; done' junk | xargs -0 rm -r
Community
  • 1
  • 1
Omnifarious
  • 54,333
  • 19
  • 131
  • 194
0

You can handle files and directories in one pass with:

tar  -tf ../test/bob.tar --quoting-style=shell-always | sed -e "s/^\(.*\/\)'$/rmdir \1'/; t; s/^\(.*\)$/rm \1/;" | sort | bash

You can see what is going to happen leave off the pipe to 'bash'

tar  -tf ../test/bob.tar --quoting-style=shell-always | sed -e "s/^\(.*\/\)'$/rmdir \1'/; t; s/^\(.*\)$/rm \1/;" | sort

to handle filenames with linefeeds you need more processing.

G. Allen Morris III
  • 1,012
  • 18
  • 30