48

I have a text file with lots of package names.

package1
package2

# comment
# installing package3 because it was needed for...
package 3

package 4

How can I mass install all packages inside the text file without removing the comments?

1
49

Something along these lines ought to do the trick.

apt-get install $(grep -vE "^\s*#" filename  | tr "\n" " ")

The $(something) construction runs the something command, inserting its output in the command line.

The grep command will exclude any line beginning with a #, optionally allowing for whitespace before it. Then the tr command replaces newlines with spaces.

4
  • 5
    tr will fail with multi-byte end-of-line sequences (think \r\n), why don't you use xargs? Feb 17 '16 at 16:20
  • You can also ignore trailing comments apt-get install $(grep -vE "^\s*#" Aptfile | sed -e 's/#.*//' | tr "\n" " ")
    – Jamie Cook
    Sep 16 '20 at 23:46
  • Just wondering, how difficult would it be to create a "dummy package", which is empty except for metadata. I know that the depends argument in the metadata is used by apt / apt-get commands as input, just as if you were to type sudo apt install <argument>. Seems like it would be a great solution to this issue. I would post myself, but I am not sure about the specifics. maybe someone a bit more experienced at package creation / handling could pick up the torch here?
    – Nate T
    Jun 18 at 14:10
  • Can this done one by one?
    – alper
    Jul 23 at 11:42
17

The following command is a (slight) improvement over the alternative because sudo apt-get install is not executed when the package list is empty.

xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install

Note that the -a option reads items directly from a file instead of standard input. We don't want to pipe a file into xargs because stdin must remain unchanged for use by apt-get.

4
  • xargs is the right way to do this. Trick with <() is neat. Feb 17 '16 at 16:19
  • 1
    That's indeed the better solution because xargs makes sure ARG_MAX is not reached.
    – phk
    Jun 12 '16 at 11:45
  • It has to be xargs -a $(awk '/^\s*[^#]/' "$packagelist") -r -- sudo apt-get -y install, not "<(" but "$(" and the option -y for apt-get would be a good idea.
    – user567188
    Jul 11 '16 at 20:19
  • 1
    Process substitution redirects the output of awk into a file descriptor for xargs -a to read from. So you definitely want <( and not $(. Just try it and you'll see what I mean. If the command is to be running unattended and you already know exactly what's going to be installed then sure, they -y flag is a good idea.
    – Six
    Jul 12 '16 at 3:01
6

Given a package list file package.list, try:

sudo apt-get install $(awk '{print $1'} package.list)
2
  • How does it help with #?
    – greatvovan
    Dec 18 '20 at 2:40
  • zsh: parse error near `} zsh: parse error near $(awk '{print $1'} p...'
    – alper
    Jul 23 at 11:44
3

I use this simple solution:

grep -vE '^#' file.txt | xargs sudo apt install -y

grep finds all lines that don't start with a # and gives them as arguments to sudo apt install.

1

Well, here's my solution to install a list of packages I have for fresh install:

sudo apt install -y $(grep -o ^[^#][[:alnum:]-]* "filename")

In a bash function :

aptif () {
    sudo apt install -y $(grep -o ^[^#][[:alnum:]-]* "$1")
}

grep explanation :

  • -o keep only the part of line that matches the expression
  • ^[^#] anything that does not start with a #
  • [[:alnum]-]* a sequence of letters, numbers and -
1

Inspired by the accepted answer here and this answer on removing comments:

    apt-get install $(grep -o '^[^#]*' filename)

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