I have a large amount of folders and files. I need to parse it and find only those with the extension xmp to finally remove them.

How can I achieve this and keep track of the name of the removed files?

To find: I know I can use find /path -name "*.xmp" But how can I run two commands on the output? keep file path and name in removelist.txt and remove it.


With GNU find's -fprint and -delete actions:

find . -name "*.xmp" -fprint "removelist.txt" -delete
  • -fprint file - print the full file name into file file. If file does not exist when find is run, it is created; if it does exist, it is truncated.
  • -delete - delete files
  • fprint is exactly what I was looking for. Thanks. – Kevin Lemaire Jan 26 '18 at 10:18

One way is to execute a compound shell command with -exec:

find /path -name '*.xmp' -exec sh -c 'echo "$1" >> removelist.txt && rm -f "$1"' sh {} \;

Inside a sub-shell both echo (appended to removelist.txt) and rm will be run against each found file.

Note: The last sh is because we are using -c. With that flag the first argument that follows is param 0 or $0 which is supposed to be the name of the shell.

Gotta admit, @RomanPerekhrest has a nicer answer for this particular case but with the technique here you can do all sorts of things for which there might not be a dedicated find flag. :)

  • Efficient answer, thanks. I've accepted the solution from existing flags but this is interesting anyway for other file manipulations. – Kevin Lemaire Jan 26 '18 at 10:20
  • @KevinLemaire You accepted the right one. :) But glad you found this one interesting. Cheers. – B Layer Jan 26 '18 at 10:21
  • Never embed the {} in the shell code! What if there's a $(reboot).xmp file? – Stéphane Chazelas Jan 26 '18 at 12:41
  • 1
    My approach/tone would have been "Instead of embedding {}, which is dangerous because of ... do this instead ...".. Anyways, with the updated format I'm no longer seeing such process substitution. – B Layer Jan 26 '18 at 21:57

To log the files that were successfully removed, you could do:

find . -name '*.xmp' -exec rm -f {} \; -print > removed.txt

The -print action will only be run if the -exec action was successful, that is if rm succeeded.

With some find implementations, you can replace the -exec rm -f {} \; with -delete to avoid running one command for each file and avoid some race conditions (initially a FreeBSD extension, but now supported by GNU find and a few others).

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.