16

I have a list of lines like

/usr/lib/i386-linux-gnu/libavfilter.so
/usr/lib/i386-linux-gnu/libavfilter.so.3
/usr/lib/i386-linux-gnu/libavfilter.so.3.42.103
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3.42.103
/usr/local/lib/libavfilter.so
/usr/local/lib/libavfilter.so.4
/usr/local/lib/libavfilter.so.4.4.100

How can I remove those files altogether instead of removing them one by one like

 rm        /usr/lib/i386-linux-gnu/libavfilter.so
 rm        /usr/lib/i386-linux-gnu/libavfilter.so.3
 rm        /usr/lib/i386-linux-gnu/libavfilter.so.3.42.103
 rm        /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so
 rm        /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3
 rm        /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3.42.103
 rm        /usr/local/lib/libavfilter.so
 rm        /usr/local/lib/libavfilter.so.4
 rm        /usr/local/lib/libavfilter.so.4.4.100

?

WARNING! Don't apply below commands without checking output at first

kenn
  • 5,232

7 Answers7

23

What's your input? A file? A command? Either way, xargs should be helpful:

cat file | xargs rm

... will delete every path for every line in the file. If it's just a command that's outputting a path on each line, pipe it through xargs and it should work well.

Alternatively, use xargs --arg-file="file.txt" rm. This saves on pipe and unnecessary cat.

If you're looking to do more with each line, you could use a traditional bash while loop:

# uses echo for testing
# remove # before rm for actual deletion
while read -r path; do
    echo "deleting $path"
    # rm "$path"
done < file

If your list is the output of find, you have another couple of options, including a -delete option or using -exec rm {} \+. There are almost certainly a few dozen other viable routes to success. If you're doing automated deletion with find, just check the output before you delete. It won't forgive you your mistakes.

Spaces can be a problem with piping things into xargs. This might not be an issue for you and your locate but both locate and xargs have a way of getting around that. They can both choose to use the \0 null character as a delimiter instead of return lines. Yay. In short, your command becomes:

locate -0b libavfilter.so | xargs -0 rm
Oli
  • 299,380
1

At the very basic level this can be done in Python:

import os

with open('input.txt') as f:
    for line in f:
        os.unlink(line.strip())

In case you have exotic filenames (such as created with touch with$'\n'backslash or with$'\n'newline, which is very bad idea, but possible ) you could use an input file as so:

./with\backspace
./with\nnewline

And handle everything in Python 3 as so:

import os

with open('./input.txt') as f:
    for l in f:
        # alternatively one can use 
        # bytes(l.strip(),sys.getdefaultencoding())
        bytes_filename =  bytes(l.strip(), 'utf-8').decode('unicode_escape')
        f_stat = os.stat(os.fsdecode( bytes_filename ) )
        print(l.strip(),f_stat)

There's a way of doing that in Python 2 as well.

1

You can put the files after eachother divided by a space. Like so:

rm /usr/lib/i386-linux-gnu/libavfilter.so /usr/lib/i386-linux-gnu/libavfilter.so.3 /usr/lib/i386-linux-gnu/libavfilter.so.3.42.103        /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3 /usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3.42.103 /usr/local/lib/libavfilter.so /usr/local/lib/libavfilter.so.4 /usr/local/lib/libavfilter.so.4.4.100
Rinzwind
  • 309,379
1

Pipe the output to xargs:

echo "/usr/lib/i386-linux-gnu/libavfilter.so
/usr/lib/i386-linux-gnu/libavfilter.so.3
/usr/lib/i386-linux-gnu/libavfilter.so.3.42.103
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3
/usr/lib/i386-linux-gnu/i686/cmov/libavfilter.so.3.42.103
/usr/local/lib/libavfilter.so
/usr/local/lib/libavfilter.so.4
/usr/local/lib/libavfilter.so.4.4.100" | xargs rm

Or if your list is in a file:

cat file | xargs rm
chaos
  • 28,186
0

The easiest way is

cat list.txt | xargs -P 3 rm 

While you can not use -P, which by default would run as many as possible, but this can be a problem if your list is large. See man pages for further explanation.

One down side for this, if your files have space in the name, this would fail. If that was not the case, you can just use, but if there were files with space in the name you expect, so that in case, make sure you specify the delimiter as newline character.

cat list.txt | xargs -d '\n' -P 3 rm 

On Mac OS, this will produce an error, but you are not on Mac OS, so you are good to use this.

Note: Since this is something that can cause loss of data/config, or cripple your install, it is always recommended that you use list the files before actually removing them. Use ls, and if the files are listed properly as expected, change to rm.

R J
  • 624
0

Here is a verbose one-liner:

while read -r line; \
do echo "Removing: $line"; \
   rm -- "$line" || echo "Failed to remove: $line"; \
   done < file
-2

use something like notepad++, go to replace (ctrl+r) enter -> find what: \r\n (be sure search mode is set to extended) and replace with: enter a space

then you have all in a line

copy it to a shell and enter rm -rf [paste file/foldernames from notepad++ here]

Klaus
  • 1