13

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

6 Answers 6

19

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
5
  • it's terminal output of locate -b libavfilter.so I am trying to remove ffmpeg that I manually installed earlier and I removed ffmpeg directory so I can not uninstall it via make uninstall
    – kenn
    Jul 9, 2014 at 17:43
  • Yeah that should be relatively safe to pipe through xargs. There are probably some people who would suggest using the -0 argument for both locate and xargs (I'll add a snippet to the answer) but I'm not sure it's really necessary here.
    – Oli
    Jul 9, 2014 at 17:46
  • beside the topic, how can I get rid of manually installed old ffmpeg remnants? I installed a few different versions of it and it causes problems in compilation process, linker adds old libraries.
    – kenn
    Jul 9, 2014 at 18:05
  • I wonder if redownloading ffmpeg, recompiling (might not be necessary) and then using sudo make uninstall might be the best idea. The wider problem you're running into is largely down the naming conflict between ffmpeg and its fork libav. Not sure there's a good way for them to coexist yet.
    – Oli
    Jul 9, 2014 at 18:13
  • Rather than running cat and piping the output to xargs, it is simpler to just run xargs rm < file and skip the cat process.
    – psusi
    Jul 9, 2014 at 21:34
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
1
  • 1
    This fails if the filenames contain spaces.
    – waldyrious
    Sep 5, 2016 at 15:28
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
  • Due to calling line.strip() this script will fail to unlik files with leading or trailing spaces in their name!
    – Semnodime
    Jan 28, 2021 at 15:49
0

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
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.

-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]

4
  • Notepad++ is a Windows product. How it can be used in Ubuntu?
    – whtyger
    Mar 8, 2016 at 13:10
  • you can either install wine first, or use any other text editor for ubuntu to do the search and replace ... with vim f.e. -> vim.wikia.com/wiki/Search_and_replace
    – Klaus
    Mar 9, 2016 at 17:57
  • 1
    yes, I know that, but you haven't mentioned that in your answer.
    – whtyger
    Mar 10, 2016 at 7:05
  • You suggest a Windows product, then you suggest installing Wine? That's not really a helpful response. I am not questioning you intent to help, but the suggestions. You could have at least suggest a Linux text editor like gedit, leafpad, ...etc, not to mention using a text editor for something easily done in terminal.
    – R J
    Sep 9, 2018 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.