18

I'm trying to remove a list of packages from a file. I'm using the following command:

cat packages | xargs sudo apt-get remove

packages is my file containing a list of packages I want to remove. Everything appears to work, but apt-get aborts instead of letting me choose yes or no.

I know I can get around this with the -y option, but I would like to know why this is happening and how can I keep the interactive choice.

2
  • How does it "work well" when it sounds like it doesn't work at all? What does an entry in your file look like? Have you tried sudo xargs --arg-file packages apt-get remove? Nov 15, 2010 at 6:00
  • Well, it kind of "works" because apt-get gets to the point of removing the right packages. That said, --arg-file was what I was looking for. You can put that in an answer and I will accept it. Thanks!
    – subb
    Nov 15, 2010 at 6:13

6 Answers 6

14
xargs -a packages sudo apt-get remove

will direct xargs to read arguments from packages, and so it will leave stdin unmolested.

10

A more general solution would be

 sudo apt-get remove `cat packages`

where you will have a problem if the list of packages is really long.

The reason that it isn't working is that apt-get is trying to read your confirmation from the standard input which - because of the pipe - is attached to cat. Contrariwise, sudo does the Right Thing by asking your password by opening /dev/tty directly. Apt should do this but apparently doesn't.

5
  • The standard input of xargs is connected to the pipe from cat, but the process started by xargs has its standard input coming from /dev/null. This is the behavior of xargs. Simple demonstration: echo "" | xargs ls -l /dev/self/fd
    – Juliano
    Nov 15, 2010 at 15:10
  • 1
    @mws: No, apt-get shouldn't open /dev/tty. Otherwise you couldn't do things like yes | apt-get. Passwords are pretty much the only case where reading from /dev/tty is the right thing, and even that much is debatable. Nov 15, 2010 at 20:21
  • Thanks for the comments, both are correct and better thought than my slap-dash response, which I'm going to leave un-edited so that the comments still make sense.
    – msw
    Nov 16, 2010 at 4:14
  • I see. Is there any difference between this and xargs -a filename, like ephemient is suggesting?
    – subb
    Nov 17, 2010 at 6:23
  • Yes, ephimemient's use of the --arg-file option is even better for the specific case which is why I upvoted it. For the many commands that don't have such an option the backtick-cat metaphor still has its uses.
    – msw
    Nov 17, 2010 at 14:09
2

Because apt-get is removing more than one package, and therefore must confirm the action. Since it's reading STDIN from a pipe and is not connected to the terminal it auto assumes No.

Another way to get around this is to add APT::Get::Assume-Yes to apt.conf.

2

Apparently xargs redirects STDIN which confuses apt-get to assume that it is running in non-interactive mode.

I would probably use something like

sudo apt-get remove $(cat packages)

to avoid using xargs at all.

("--arg-file" is neither in apt-get(8) man nor in my active vocabulary).

1

To work around.

With GNU xargs and ksh/zsh/bash:

sudo xargs -r --arg-file <(cat packages) apt-get remove

(of course, if the command is just cat, then you can replace <(cat packages) with packages.

Or:

< packages sudo xargs sh -c 'exec apt-get remove "$@" < /dev/tty' sh

Depending on the format of the "packages" file (xargs is expecting a blank-separated list of arguments and processes quotes (", ' and \), while $(...) doesn't process quotes and expands globbing patterns), you could also do:

sudo apt-get remove $(cat packages)

But please note that many operating systems have a limit on the length of a command line, so that may not work if the list is big (while xargs will work around the issue by running several apt-get commands).

0

I may be wrong, but you can try this and see if it works:

yes | sudo apt-get remove $(cat packages)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .