Skip to content

How to redirect stderr but continue to pipe stdout? #10271

@bobhy

Description

@bobhy

Question

I'm having trouble invoking an external command and redirecting stderr (to /dev/null) while piping stdout to the next step.
Maybe there's some other kind of redirection I should be using? Maybe it's a bug?

Sample:

> sudo apt update  | filter {|line| $line | str contains --ignore-case "can be upgraded" } 

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

╭───┬──────────────────────────────────────────────────────────────────────╮
│ 0 │ 6 packages can be upgraded. Run 'apt list --upgradable' to see them. │
│   │                                                                      │
╰───┴──────────────────────────────────────────────────────────────────────╯

Almost what I want, except for the ugly WARNING that didn't flow into the pipe.

(try to) Fix it by redirecting stderr:

> sudo apt update  err> /dev/null | filter {|line| $line | str contains --ignore-case "can be upgraded" } 
Hit:1 http://us.archive.ubuntu.com/ubuntu lunar InRelease
Hit:2 http://us.archive.ubuntu.com/ubuntu lunar-updates InRelease                                                      
Hit:3 http://packages.microsoft.com/repos/code stable InRelease                                                        
Hit:4 http://us.archive.ubuntu.com/ubuntu lunar-backports InRelease                                                    
Hit:5 https://packages.microsoft.com/repos/edge stable InRelease                                                       
Hit:6 http://security.ubuntu.com/ubuntu lunar-security InRelease           
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
6 packages can be upgraded. Run 'apt list --upgradable' to see them.

Does suppress the WARNING, but now filter isn't getting any input...

At first I though this had something to do with sudo, but you can repro with nonprivileged external dir command

> dir -l .  argle  | filter {|x| $x | str contains Music}
dir: cannot access 'argle': No such file or directory
╭───┬────────────────────────────────────────────────────────╮
│ 0 │ .:                                                     │
│   │ total 89                                               │
│   │ drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Desktop      │
│   │ drwxr-xr-x 2 bobhy bobhy   3 Sep  6 14:20 Documents    │
│   │ drwxr-xr-x 2 bobhy bobhy  25 Sep  6 23:47 Downloads    │
│   │ drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Music        │
│   │ drwxr-xr-x 3 bobhy bobhy   3 Aug 25 13:18 Pictures     │
│   │ drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Public       │
│   │                                                        │
╰───┴────────────────────────────────────────────────────────╯

The missing directory error is reported to stderr as in the previous case.

I don't quite get why each newline-delimited line of output wasn't broken into a separate line item, like it seems to have done with sudo apt, but never mind: the key thing is filter returned a list with one element, as desired.

> dir -l .  argle err> /dev/null  | filter {|x| $x | str contains Music}
.:
total 89
drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Desktop
drwxr-xr-x 2 bobhy bobhy   3 Sep  6 14:20 Documents
drwxr-xr-x 2 bobhy bobhy  25 Sep  6 23:47 Downloads
drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Music
drwxr-xr-x 3 bobhy bobhy   3 Aug 25 13:18 Pictures
drwxr-xr-x 2 bobhy bobhy   2 Aug 18 21:12 Public

Note that the dir output isn't being piped into filter,at all, apparently.

Additional context and details

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A:redirection-pipeAll related to redirection to files or more complex pipelines with STDERRdeprecated:questionQuestions should be redirected to GitHub discussions

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions