Delete folders which not match a list

Assuming your file names do not contain any of :\[*?, you could still use GLOBIGNORE. Just format your list of directories accordingly. For example:

$ cat names.txt
folder1
folder3

That is very easy to transform into a colon separated list:

$ paste -s -d : names.txt
folder1:folder3

So, you can now set that as the value of GLOBIGNORE:

GLOBIGNORE=$(paste -s -d : ../names.txt)

And proceed to delete them normally:

rm -r -- *

I just tested this on Linux with 300 directories and it worked perfectly.


Another solution that matches begin and end of the folder names:

IFS=$'\n'

folders="""folder1
folder2"""

for folder in *; do
    found=0
    if [ -d "$folder" ]; then
        for i in $folders; do
            if [ $(echo "$folder" | grep -c -E "^$i\$") -eq 1 ]; then
                found=1
            fi
        done
        if [ $found -ne 1 ]; then
            echo "$folder found and deleted."
            rm -rf "$folder"
        fi
    fi
done

A simple approach is to list all files and ignore the ones that are in the list file. Note that I arrange for the variable ignore_list to start and end with a newline, so that I can check if $x is included in a simple way (just checking that $ignore_list contains $x doesn't work, since it would also match files whose name is a substring of an element of the ignore list).

newline='
'
ignore_list="$newline$(cat list.txt)$newline"
cd target_folder
for x in * .[!.]* ..?*; do
  case "$x" in *"$newline"*) continue;; esac   # sanity check: if the file name contains a newline, leave it alone
  case "$ignore_list" in
    *"$newline$x$newline"*) echo "Skipping $x";;
    *) rm -rf -- "$x";
  esac
done