1

I have a folder with huge number of files.

I want to delete the following files from the folder.

ni_mayb17000.mol2  
ni_mayb50000.mol2
ni_fda.mol2
ni_mayb2000.mol2
ni_mayb5000.mol2
ni_in_trials1000_2999.mol2   
ni_in_trials1-999.mol2        
ni_in_trials5000.mol2         
ni_intrials8000.mol2          
ni_intrialsfinal.mol2        
ni_mayb13000.mol2
ni_mayb21000.mol2
ni_mayb45000.mol2
ni_mayb55000.mol2
ni_mayb25000.mol2
ni_mayb60000.mol2
ni_mayb30000.mol2
ni_mayb8000.mol2
ni_mayb35000.mol2
ni_mayb_f.mol2
ni_mayb40000.mol2 
ni_world_not_fda.mol2

The files which need to be deleted does not follow a particular pattern, so I was not able to use wild card or pattern. Also if I use patterns, I have risk of deleting unintended files. Since I know the exact file name to be deleted, I was planning to store the required files as a list and then delete it using a for loop

for i in $list; do
   rm $i -f; 
done

How to store this as a list and then do this for list?

Praveen Kumar-M
  • 592
  • 5
  • 15

3 Answers3

5

The issues with using for i in $list is described in "Why does my shell script choke on whitespace or other special characters?" and "Security implications of forgetting to quote a variable in bash/POSIX shells".

Assuming name.list contains a manually curated list of filenames referring to files in the current directory, with one filename on each line:

while IFS= read -r name; do
    rm -f "./$name"
done <name.list

This reads each name into the variable name, and rm -f is called with the variable's value. If the file does not exist, no error will be outputted (due to the -f). The value in $name will have ./ prepended to it before rm is called to restrict the effects of the deletion to the current directory.

A slightly more elaborate variant that produces a bit of output as it goes through the list of filenames:

while IFS= read -r name; do
    if [ -e "./$name" ]; then
        printf 'Removing "%s"\n' "$name"
        rm -f "./$name"
    else
        printf 'Did not find "%s"\n' "$name"
    fi
done <name.list

Or, using xargs:

xargs -t -I {} rm -f ./{} <name.list

This would call rm -f with the contents of each line of the file name.list. The -t option to xargs enables "trace mode", which would show each command executed by xargs.

Kusalananda
  • 333,661
4

If you have them in a file, say filelist.txt, you could try the following loop

while IFS= read -r filename
do
   rm "$filename"
done < filelist.txt

Always test, however, before actually erasing the files (e.g. by replacing the rm "$filename" with echo "Would now remove $filename").

AdminBee
  • 22,803
2

If you know the exact file name(s) to be deleted, then just remove them directly:

rm file1 file2 ...

and skip the step of saving them to yet another file and re-reading that file with a shell loop. You then probably want to remove that filename afterwards! Efficiency is in the eye of the beholder, but rm file1 ... is one command while other methods are several steps and prone to accidents if you omit quoting or other shell gotchas.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255