Reputation: 458
Hi I have a peculiar problem and I'm trying hard to find (pun intended) a solution for it.
$> find ./subdirectory -type f 2>>error.log
I get an error, something like, "find: ./subdirectory/noidea: Permission denied" from this command and this will be redirected to error.log.
Is there any way I can pipe the stderr to another command before the redirection to error.log?
I want to be able to do something like
$> find ./subdirectory -type f 2 | sed "s#\(.*\)#${PWD}\1#" >> error.log
where I want to pipe only the stderr to the sed command and get the whole path of the find command error.
I know piping doesn't work here and is probably not the right way to go about.
My problem is I need both the stdout and stderr and the both have to be processed through different things simultaneously.
EDIT: Ok. A slight modification to my problem.
Now, I have a shell script, solve_problem.sh
In this shell script, I have the following code
ErrorFile="error.log"
for directories in `find ./subdirectory -type f 2>> $ErrorFile`
do
field1=`echo $directories | cut -d / -f2`
field2=`echo $directories | cut -d / -f3`
done
Same problem but inside a shell script. The "find: ./subdirectory/noidea: Permission denied" error should go into $ErrorFile and stdout should get assigned to the variable $directories.
Upvotes: 4
Views: 4444
Reputation: 7218
Pipe stderr and stdout simultaneously - idea taken from this post:
(find /boot | sed s'/^/STDOUT:/' ) 3>&1 1>&2 2>&3 | sed 's/^/STDERR:/'
Sample output:
STDOUT:/boot/grub/usb_keyboard.mod
STDERR:find: `/boot/lost+found': Brak dostępu
Bash redirections like 3>&1 1>&2 2>&3
swaps stderr and stdout.
I would modify your sample script to look like this:
#!/bin/bash
ErrorFile="error.log"
(find ./subdirectory -type f 3>&1 1>&2 2>&3 | sed "s#^#${PWD}: #" >> $ErrorFile) 3>&1 1>&2 2>&3 | while read line; do
field1=$(echo "$line" | cut -d / -f2)
...
done
Notice that I swapped stdout & stderr twice.
Small additional comment - look at -printf
option in find manual page. It might be useful to you.
Upvotes: 3
Reputation: 36402
You can try this (on bash), which appears to work:
find ./subdirectory -type f 2> >(sed "s#\(.*\)#${PWD}\1#" >> error.log)
This does the following:
2>
redirects stderr to>(...)
a process substitution (running sed, which appends to error.log)Upvotes: 1
Reputation: 40374
If you need to redirect stderr
to stdout
so that the following command in the pipe gets it as its input, then you can use 2>&1
.
For more information, please have a look at the all about redirection how-to.
Edit: Even if you need to edit pass stdout
further in the pipe, you can use sed
to filter error messages and write them to a file:
$ find . -type f 2>&1 | sed '/^find:/{
> w error.log
> d
> }'
In this example:
find
command stderr
is redirected to stdout
sed
command errors from find
that match a regular expression are written to a file (w error.log
) and removed from output (d
).find
.Note: This will work as lon as all the error messages from find
start with find:
. Otherwise, the regular expression in sed
should be modified to properly match all cases.
Upvotes: 2