In my root directory, I have a couple folders named something like AA, BB, CC etc., each containing files in the format AA1001.txt, BB1002.txt etc.
In my root folder, I also have a file all_to_delete which has a bunch of file names separated with newlines, thus looking something like this:
AA1004.txt
BB3004.txt
BB3005.txt ...
I now want to go through all subdirs in my root directory and delete all files that match the given filename. Until now, I have tried something like:
while read line; do find . -type f -name $line -exec rm -f {} \;; done
Though, this cannot work as already while read line; do find . -type f -name $line; done does not match any file (as the find gives its output as ./AA/AA1001.txt ...)
Do you guys have a solution for me?
Answer
Given a file with filenames, the easiest thing to do would be to read it line by line, and pass it to find. However, this will result in a separate instance of find for each file name and can become very slow for large lists of files and many files in a directory tree.
Instead, I would do something like this:
find . -type f -name "*txt" | grep -wFf to_delete.txt | xargs -I{} rm '{}'
The trick is to give grep your file as a list of patterns to search for (-f). The -F makes sure your filenames are treated as strings and not regular expressions, that way your file names ca contain special characters like * or [ or |. You then pass to xargs and use quoted '{}', otherwise it fails on white space, to delete the files.
NOTE: This assumes that your file names are all unique, that one name cannot be contained in another. For example, that you don't have files called foo and foobar. If you do, given a pattern foo, this will delete both files. To avoid this use:
while IFS= read -r line; do find . -name "$line" -delete; done < to_delete.txt
From man find:
-delete
Delete files; true if removal succeeded.
No comments:
Post a Comment