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