I have a text file with lots of package names.


# 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?


6 Answers 6


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.

  • 5
    tr will fail with multi-byte end-of-line sequences (think \r\n), why don't you use xargs? Feb 17, 2016 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, 2020 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, 2021 at 14:10
  • Can this done one by one?
    – alper
    Jul 23, 2021 at 11:42

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.

  • xargs is the right way to do this. Trick with <() is neat. Feb 17, 2016 at 16:19
  • 1
    That's indeed the better solution because xargs makes sure ARG_MAX is not reached.
    – phk
    Jun 12, 2016 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, 2016 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, 2016 at 3:01
  • Would it be still run if one of the packages in the list crashes to be installed?
    – alper
    Mar 6, 2022 at 14:42

Given a package list file package.list, try:

sudo apt-get install $(awk '{print $1'} package.list)
  • How does it help with #?
    – greatvovan
    Dec 18, 2020 at 2:40
  • zsh: parse error near `} zsh: parse error near $(awk '{print $1'} p...'
    – alper
    Jul 23, 2021 at 11:44
  • This is a good solution, but slightly incorrect. The second ' character is slightly misplaced. The correct syntax is: sudo apt-get install $(awk '{print $1}' package.list)
    – kai
    Sep 5 at 21:21

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.


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

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

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 -
  • I needed to add a . after [:alnum:] in order to support package names with a .. Jan 26 at 12:12

You must log in to answer this question.

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