It looks like you've got a solution that works, but I thought I'd offer this one as well, as it might still be of help to you or someone else.
find /Path/To/TestDir -type f ! -name '.*' -exec basename {} + | grep -xvF -f /Path/To/filenames.txt"
Breakdown
find
: This gets file paths in the specified directory (which would be TestDir
) that match the given criteria. In this case, I've specified it return only regular files (-type f
) whose names don't start with a period (-name '.*'
). It then uses its own builtin utility to execute the next command:
basename
: Given a file path (which is what find
spits out), it will return the base filename only, or, more specifically, everything after the last /
.
|
: This is a command pipe, that takes the output of the previous command to use as input in the next command.
grep
: This is a regular-expression matching utility that, in this case, is given two lists of files: one fed in through the pipe from find
—the files of your TestDir
directory; and the files listed in filenames.txt
. Ordinarily, the filenames in the text file would be used to match against filenames returned by find
, and those that match would be given as the output. However, the -v
flag inverts the matching process, so that grep
returns those filenames that do not match.
What results is a list of files that exist in the directory TestDir
, but do not appear in the filenames.txt
file. These are the files you wish to delete, so you can simply use this line of code inside a parameter expansion $(...)
to supply rm
with the files it's able to delete.
The full command chain—after you cd
into TestDir
—looks like this:
rm $(find . -type f ! -name '.*' -exec basename {} + | grep -xvF -f filenames.txt")