Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm a Linux user. I accidentally downloaded a bunch of files into the wrong directory. They're now mixed in with my other files. I then created a new subdirectory and downloaded all the files again, this time into the subdirectory. What is the best way to remove all of the files I accidentally downloaded to the directory without accidentally deleting any of my existing files. I'm new to Linux and need some help. I suppose it could be down by date, or it could be done by saying for each file in the subdirectory, delete a file in the directory with the same name. Thanks in advance! -- Larry

share|improve this question

migrated from stackoverflow.com Sep 8 '09 at 20:01

This question came from our site for professional and enthusiast programmers.

    
Do you have a problem with spaces in the names, or is everybody waxing academic? –  Nathan Fellman Sep 9 '09 at 7:44
add comment

5 Answers

If the file modification times are consistent, then you can use a variant on touch and find to locate the files to be removed. Suppose you downloaded the files just after 12:34 today (2009-09-08):

touch 20090908123400 empty.file
find . -newer empty.file -print

This will list the files. When you're sure you've got the right files, you can revise the find command to:

find . -newer empty.file -print0 | xargs -0 rm -f

Using the '-print0' and '-0' options means that the pipeline will handle file names with spaces and all other special characters correctly. You could also use -older and a second empty file with a different time stamp to frame the time.

If the downloads preserved the modification times of the files on the remote system, you are probably hosed. However, that is rather unlikely to be a problem.

share|improve this answer
2  
no need for -print0 | xargs ..., which doesn't work when you have a lot of files. Find has a -delete flag which is both correct and fast. –  Peltier Sep 8 '09 at 23:40
    
POSIX standard find does not have a -delete flag, so that isn't wholly portable - but then it doesn't have -print0 either, so beyond "I wasn't aware of -delete, and it was a good idea to add it to find", there isn't a lot more to say. –  Jonathan Leffler Sep 9 '09 at 2:39
add comment

Actually this is very easy to do. cd into the directory that you accidentally downloaded the files and run the following code, replacing subdirectory with the name of the subdirectory that contains the files you downloaded a second time.

rm `ls subdirectory`

What this does is list all of the contents in subdirectory and this list is passed to rm which Re Moves any files with the same name in the current directory.

share|improve this answer
2  
Doesn't work for files with spaces in their names. –  Tim Sep 8 '09 at 20:21
    
I tried to fix that by adding some options to ls but they do not act as expected. Hopefully it won't be an issue for OP since most downloaded files do not have spaces in them. –  Alvin Row Sep 8 '09 at 20:36
    
If you need to remove everything in the sub-directory, then "rm -fr subdirectory" is the most reliable way to do it, not least because it works even if the files in the subdirectory contain spaces and the like. –  Jonathan Leffler Sep 8 '09 at 20:49
    
Also, my impression from the question is that the user has files to keep as well as files to remove, so blanket removal of a sub-directory is not part of the answer. –  Jonathan Leffler Sep 8 '09 at 20:53
    
I hope you didn't down vote me because this does NOT remove files in the subdirectory. I deletes files in the current directory that have the same name as a file in the subdirectory. –  Alvin Row Sep 8 '09 at 21:41
show 2 more comments

To expand on Pynt's conceptually correct solution, you can handle files with spaces in their names by using the null-separator options of find and xargs:

Suppose your downloads folder is ~/Downloads/, which contains the files file 4 and file 5. You actually wanted to download a set of files (file 1, file 2, and file 3) to a subdirectory ~/Downloads/subdir/. You accidentally downloaded those files to ~/Downloads/, then you downloaded them correctly to ~/Downloads/subdir/ as well. So, your current situation looks like this:

$ tree ~/Downloads/
.
|-- file 1
|-- file 2
|-- file 3
|-- file 4
|-- file 5
`-- subdir
    |-- file 1
    |-- file 2
    `-- file 3

To delete the right files, try this:

$ cd ~/Downloads
$ { pushd subdir; find -mindepth 1 -maxdepth 1 -print0; popd; } |\
  xargs --null -I'{}' trash '"{}"

That code will not delete the files. It will send them to the trash instead, as long as you have installed the trash-cli package. (See http://superuser.com/questions/32355/undo-linuxs-rm/32480#32480 for more info on the trash command, which I highly recommend.) If you'd rather live dangerously, replace trash with rm. If you want to live even less dangerously, replace trash with echo trash. That will simply print the commands that will delete your files.

Anyway, here's the explanation, since you should never trust code you don't understand. The first line simply moves into the Downloads directory. The second line finds and prints the names of all the files in subdir. pushd and popd are just like cd, only with a back button. (Look up stacks if you wonder where "push" and "pop" come from.) The options to find tell it to only list things in subdir and not, for example, subdir/another subdir/third subdir. They also tell it not to list ., the name for the current directory itself. You don't want to remove that. Lastly, the -print0 option tells find to print the files it finds, but separate them with null characters instead of whitespace. This is how we deal with spaces.

Likewise, in the third line, the --null option to xargs tells it to read the filenames from find with null characters separating them. The rest of the third line constructs the command that will delete your files.

The lesson in general is that you need to process files that might have spaces, you generally need to use a command that involves find -print0 | xargs --null.

share|improve this answer
add comment

Simple bash solution

cd subdir
for i in *
do
    rm "../$i"
done

I haven't tested it, so you'd better test it before you run it for real :)

share|improve this answer
add comment

Pynt and Peltier have this basic idea, but only Peltier's will handle files with whitespaces.

This should work:

cd path-to-subdirectory
set -- *
cd -
ls -ld "$@" | more    # Make sure the list is what you expect to remove, then:
rm -rf "$@"

I show using "ls" to confirm the file list before removal, for sanity.

But you could also move them to a temporary place (including a ZIP archive) if you're concerned about deleting the wrong stuff. Just replace the "rm" above with either of the following, then if you trust what happened, remove the ZIP or temporary directory:

mkdir /tmp/to-nuke ; mv -vi "$@" /tmp/to-nuke
zip -0rm backup.zip "$@"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.