12

Cannot get why

$ apt-cache policy foo
N: Unable to locate package foo

but

$ apt-cache policy foo 2>&1 | grep .

is empty.

Where in the latter call am I doing the wrong assumption?

The original task: I need to process the apt-cache policy output presumably :-)

UPD:

foo used in my example may be substituted with any package name that does not exist in your apt-get index.

UPD 2:

there is an answer with a workaround. Additional +50 bounty will be awarded to anyone who explains why the 2>&1 solution does not work.

  • # apt-cache policy vim 2>&1 |grep . vim: Installed: 2:7.4.712-2 Candidate: 2:7.4.712-2 Version table: *** 2:7.4.712-2 0 500 http://ftp.debian.org/debian/ sid/main amd64 Packages 100 /var/lib/dpkg/status – PersianGulf May 6 '15 at 21:02
  • 1
    @MohsenPahlevanzadeh that's right, now try the exact call (package name) I provided :-) – zerkms May 6 '15 at 21:03
  • 3
    @MohsenPahlevanzadeh so? I'm sorry, but are you sure you have read the question (and the title)? – zerkms May 6 '15 at 21:06
  • 2
    @MohsenPahlevanzadeh not it's not equal (not even close) – zerkms May 6 '15 at 21:09
  • 1
    I run strace apt-cache policy foo 2>&1 and there is a system call ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 I think because of this call 1(stdout) has problems. I mean it is not written to tty anymore – Esref May 6 '15 at 22:16
11

If stdout is not a tty (i.e. it's a regular file or a pipe) and if no --quiet option has been specified, apt-cache acts as if you had passed it --quiet=1. A workaround is to pass it a --quiet=0 option.

$ apt-cache --quiet=0 policy foo 2>&1 | grep .
N: Unable to locate package foo
10

There seems to be some cheaty behavior for redirections in apt-cache. But we can cheat a cheater by swapping stdout and stderr!

Try this one, it should work:

apt-cache policy foo 3>&1 1>&2 2>&3 3>&- | grep .
7

If you run strace apt-cache policy foo 2>&1 command, you can see the line ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0

Because that command manipulates the 1(stdout), 1 is not written to stdout anymore. And if you redirect 2 to 1, you lost both of them.

Edit: Here is a some code sample from apt-cache source code:

// Deal with stdout not being a tty
   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
      _config->Set("quiet","1");
  • Okay. Any way to capture them both? – zerkms May 6 '15 at 23:05
  • 1
    I could not find any way other than like @Mr_Mig's answer. (Mine was apt-cache policy foo 1>&2 2>&1 | grep .) But I find that in the source code apt apt-cache :) // Deal with stdout not being a tty if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); – Esref May 7 '15 at 0:39
  • Btw, I also was pointed by someone to the same point in sources just few minutes ago :-) And a potentially better solution script -c "sudo apt-cache policy foo" | grep Unable which requires installing a script though. As advised - I will put +50 here in 2 days (SE does not let to do it earlier) – zerkms May 7 '15 at 0:55
  • 2
    @Esref Your comment about "I find that in the source code apt apt-cache..." should be in the answer, so please add it there. +1. : – Faheem Mitha May 7 '15 at 9:08
  • Oh god, there is no +50 bounty option anymore :-( – zerkms May 10 '15 at 4:31
3

A "better" solution would be to use a script utility:

script -c "apt-cache policy foo" /dev/null | grep .

That way it intercepts all the output and forwards it to the stdout.

The only drawback is that you need to install the script if you don't have it yet. In ubunty it's provided by bsdutils package.

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.