8

I'm not too familiar with find and managed to delete a ton of files by accident. I was wondering if anyone more experienced could explain where I went wrong.


I wanted to clean up all of the .DS_Store and ._.DS_Store files that my MacBook's Finder was barfing all over my Raspbian samba share.

  • I have a hard drive attached to my raspberry pi, with some symlinks in my home folder to the mounting point, hence the -L.
  • Some of the folders are owned by system users (e.g. apache) hence the sudo.

I ran the following to make sure that find was targeting the right files:

hydraxan@raspberry:~ $ sudo find -L . -maxdepth 255 -name \*DS_Store\*
./.DS_Store
./Downloads/USBHDD1/._.DS_Store
./Downloads/USBHDD1/.DS_Store
./Downloads/USBHDD1/backups/ALAC/._.DS_Store
./Downloads/USBHDD1/backups/ALAC/Jeff Van Dyck - Assault Android Cactus OST/._.DS_Store
./Downloads/USBHDD1/backups/ALAC/Jeff Van Dyck - Assault Android Cactus OST/.DS_Store
./Downloads/USBHDD1/backups/ALAC/.DS_Store
./Downloads/USBHDD1/backups/._.DS_Store
./Downloads/USBHDD1/backups/.DS_Store
./Downloads/USBHDD1/backups/OriginalMusic/._.DS_Store
./Downloads/USBHDD1/backups/OriginalMusic/.DS_Store
./Downloads/USBHDD1/backups/OriginalMusic/FLAC/.DS_Store
./Downloads/USBHDD1/backups/Storage/._.DS_Store
./Downloads/USBHDD1/backups/Storage/.DS_Store
./Downloads/OriginalMusic/._.DS_Store
./Downloads/OriginalMusic/.DS_Store
./Downloads/OriginalMusic/FLAC/.DS_Store
./Downloads/ALAC/._.DS_Store
./Downloads/ALAC/Jeff Van Dyck - Assault Android Cactus OST/._.DS_Store
./Downloads/ALAC/Jeff Van Dyck - Assault Android Cactus OST/.DS_Store
./Downloads/ALAC/.DS_Store

All looks good!

I then added the -delete flag to cause find to remove the files it found:

hydraxan@raspberry:~ $ sudo find -L . -maxdepth 255 -delete -name \*DS_Store\*
find: cannot delete `./Documents': Not a directory
find: cannot delete `./Pictures': Not a directory
find: cannot delete `./Music': Not a directory

Once I realized it was trying to delete my symlinks for some reason, I punched Ctrl+C and saved about half the data.

Documents, Pictures, and Music are toast. It was probably working on my giant Downloads folder that I put nearly everything in.


Why did find delete all those files? Did I put -delete in the wrong spot?

14

Your answer is in find manpage.

The delete option is processed before your name filter.

       -delete
          Delete files; true if removal succeeded.  If the removal failed,
          an  error message is issued.  If -delete fails, find's exit sta‐
          tus will be nonzero (when it eventually exits).  Use of  -delete
          automatically turns on the -depth option.

          Warnings:  Don't  forget that the find command line is evaluated
          as an expression, so putting -delete first will make find try to
          delete everything below the starting points you specified.  When
          testing a find command line that you later intend  to  use  with
          -delete,  you should explicitly specify -depth in order to avoid
          later surprises.  Because -delete  implies  -depth,  you  cannot
          usefully use -prune and -delete together.

You could have moved the delete option as the last one of your command

Alternatively, you could have used something like

find /path -name "*pattern*" | xargs rm -f

or

find /path -name "*pattern*" -exec rm -f {} \;
|improve this answer|||||
  • 1
    +1 except xargs, exec don't solve the problem at all (same pitfall, if you add -print0 or -exec at the beginning instead of the end). – frostschutz Jan 13 '17 at 1:25
  • 1
    Ah, I misread the man page. I thought it was saying that -delete needs to be after the path ("starting point"), not the pattern. – Hydraxan14 Jan 13 '17 at 1:26
  • 4
    @Hydraxan14 the point is that things are processed left to right so your command was find things which are less than 256 directory levels down and delete them and whose name contains DS_Store – icarus Jan 13 '17 at 2:41
  • @icarus Paraphrasing the command like that helps me understand it a lot better. Thanks! I'm used to other *nix commands which don't care where flags go. – Hydraxan14 Jan 13 '17 at 15:51
  • 1
    @Hydraxan14 Many commands cares about the order of command line flags. Compare, for example, ls -1 -l with ls -l -1. – Kusalananda Jan 13 '17 at 19:00
1

The basic principle of the command line of find is “if condition and condition and … then action”. Note that the action comes last — it's quite different from the format of calling a command which is “action object object …”.

For example, find . -name \*DS_Store\* -delete means “if the name matches *DS_Store* then delete”. If you reverse the condition and the action, the -delete action has no condition behind it, so it's applied unconditionally.

The reason why find . -delete -name \*DS_Store\* is not a syntax error is that actions are also conditions. The -delete action is a true condition if it succeeds, and is false if it fails (e.g. due to a lack of permissions). For example, find . -name somethingorother -delete -print prints the names of the files that are successfully deleted.

The reason why find -name \*DS_Store\* is not a syntax error is that if there is no action, then there is an implicit -print action. It was designed this way because printing is a very common choice of action.

(Note that while my answer does not contain an outright lie, it does simplify some things. There are features of find that the explanations in my answer does not cover, in particular the ! and -o logical operators.)

|improve this answer|||||

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.