I copied a directory using this:

cp -r dir/ ../../

without thinking and realized that it copied the contents of dir instead of actually dir to the above directory. Now I have a mess of files I need to delete so I can redo the cp correctly. How can I delete all the files that I mistakenly copied over if they don't match anything in particular?


Ok, this is basically the same as klapaucius' answer. (And it won't repair any damage done if cp has overwritten some existing files.)

Assuming you are in the source directory (in dir). This command:

find . -type f echo '{}' ';'

will list all the files (recursively) present in your dir directory (quite like -print). The -type f option is there to prevent the listing of sub-directories.

So, if you use:

find dir -type f -exec echo '../../../{}' ';'

This should list corresponding files (copies) in the target directory.

Now if the list is correct, you will be able to remove the copies using:

find dir -type f -exec rm -- '../../../{}' ';'

As for pruning remaining empty directories that come from the cp… hum…

  • I'm using the echo method to double check the file names first. However, I need to change dir to . or else it doesn't seem to work. Also, it only lists the files in dir, not the ones also in ../.. – n0pe Aug 31 '11 at 13:11
  • Ah yes, I got confused by your description. Why did cp copy the content and not the directory in this case? – Stéphane Gimenez Aug 31 '11 at 13:16
  • 1
    Ah! that's cause of the final /! – Stéphane Gimenez Aug 31 '11 at 13:24
  • 1
    The one in ./dir/? Should it have been ./dir instead? – n0pe Aug 31 '11 at 13:27
  • 1
    Yes, but this happens only with some cp versions it seems… Mine (coreutils 8.12) has not this behavior anymore. (It was useful sometimes.) – Stéphane Gimenez Aug 31 '11 at 13:31

Use find in combination with -exec. Better test with ls before like this:

find . -name "*" -exec ls ../../{} \;
  • What exactly is this doing? For every file in . (the copied dir), it sees if it is also two directories up? To remove them I use rm instead of ls? – n0pe Aug 31 '11 at 12:24
  • Yes, exactly. Sorry, forgot to explain it – klapaucius Aug 31 '11 at 12:34
  • Dont worry about it, I'll test this first before trying it on my server :) – n0pe Aug 31 '11 at 12:41
  • I get find: missing argument to '-exec' – n0pe Aug 31 '11 at 12:45
  • Do you have a blank between {} and \; ? – klapaucius Aug 31 '11 at 12:57

The following code handles file names which contain embedded newlines I've put a full version script on paste.ubuntu. It checks for existance and matching sizes... The code to generate the test data is also included there.

# This lists the original fully-qualified filename, 
# and its would-be counterpart (assuming it exists) 
unset a i
while IFS= read -r -d $'\0' relf; do
    printf "%s\n$s" "$PWD${relf:1}" "$(dirname "$(dirname "$PWD")")${relf:1}"
done < <(find  . -type f  \! -name '.' -name '*' -print0)

Here is a sample output of the full version (mentioned above), where one file is missing, and another has a different file size to the original

NOT in target   ./file1
ok --------
sizes match     ./c/file4-in-subdir
WARNING ------
size mis-match  ./file3   is   triple-spaced
ok --------
sizes match     ./file2
has newline!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.