Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Let us say I redirect the STDOUT, STDERR of a program to files.

./script.sh 1> output.log 2> error.log

Can the running program find this out i.e. know the paths to these files?

share|improve this question
add comment

4 Answers 4

up vote 2 down vote accepted

You can call lsof to list the open files of the shell process. Use -a -p $$ to limit the output to the shell process ($$), -d 1 to limit the output to file descriptor 1 (for instance), and -F n to print the output in parseable form. Here's a shell snippet that copes with arbitrary characters in file names:

output_file=$(lsof -a -p $$ -d 1 -F pn; echo .)
output_file=${output_file%.}
output_file=${output_file#n}

If the file name doesn't contain a newline, you'll be able to get away with output_file=$(lsof -a -p $$ -d 1 -F pn | sed -n '2s/.//p').

Note that the file name may not always exist, in particular if the file has been deleted.

Under Linux, another way to access the file names is through /proc/$$/fd: /proc/$$/fd/1 is a slightly magic symbolic link to the file opened by the shell on file descriptor 1 (the link works even if the file name returned by readlink doesn't exist, for example in the case of a deleted file).

It is usually a very bad idea to make any use of the information obtained this way. If someone calls your script with the output redirected to a file, they won't like it if you behave differently because of the location of the file, or affect the file in ways other than appending to it. There is one exception: you may want to react differently depending on whether you're writing to a terminal or to something else (pipe, socket, file), for example to display colors or progress indicators on a terminal. There is a specific test to determine whether a file descriptor is connected to a terminal:

if [ -t 2 ]; then
  # stderr is a terminal
  printf 1>&2 '\e[31mError: widget not found\e[0m'
else
  # stderr is not a terminal
  echo 1>&2 'Error: widget not found'
fi
share|improve this answer
    
This is good - but it depends on lsof, of course. Though not the last bit, obviously. –  mikeserv Apr 7 at 21:10
    
@mikeserv That's the portable way to do it. I do also mention the Linux way. –  Gilles Apr 7 at 21:14
    
I should clarify - lsof is awesome - its just not always there. Neither is readlink for that matter - though I think the chances are a little better. - I agree. I was writing that addendum before even I knew you had replied. Speaking of readlink - my preference is for realpath, actually. –  mikeserv Apr 7 at 21:15
    
In any case, it would be hard to argue you did a worse job of explaining it than anyone else did here - especially me. You've already got my vote. –  mikeserv Apr 7 at 21:22
    
@mikeserv If /proc/<pid>/fd is there, then there's a very good chance that you're running Linux (but it could also be Solaris or some other SysV unices) and therefore readlink is available (it's in GNU coreutils and BusyBox). realpath is less common: under Linux, it's a deprecated program from the time before readlink, which may still be installed if some legacy application depends on it. –  Gilles Apr 7 at 21:23
show 2 more comments
{ readlink /dev/fd/[1,2] ; echo "out" ; } >./file 2>./error    
{ readlink /dev/fd/0 ; cat ; } <./file

OUTPUT:

/home/mikeserv/file
/home/mikeserv/file
/home/mikeserv/error
out

{ readlink /proc/$$/fd/[1,2] ; echo out ; } >./file 2>./error
{ readlink /proc/$$/fd/0 ; cat ; } <./file

OUTPUT:

/home/mikeserv/file
/home/mikeserv/file
/home/mikeserv/error    
out
share|improve this answer
4  
This is useful, but it should be noted that not all unixes implement the proc file systems. –  Jenny D Apr 7 at 9:01
    
A very useful note indeed. –  mikeserv Apr 7 at 9:02
    
Although, to be fair, the unixes 99 % of the people posting here use do... :-) –  Jenny D Apr 7 at 9:03
1  
@JennyD - when I hover my mouse cursor over the ^ arrow next to an answer it says - "This answer is useful..." –  mikeserv Apr 7 at 9:06
    
thanks for the reminder, got distracted by actual work :-) –  Jenny D Apr 7 at 9:14
show 5 more comments

In your case, STDOUT will be saved to file output.log and STDERR will be saved to file error.log. Both files are saved in the same directory with script.sh.

If you want your program "know the path to these files", you must use absolute path:

./script.sh > /path/to/output.log 2> /path/to/error.log
share|improve this answer
add comment

The output.log and error.log files are created in the current directory i.e. the $PWD variable value. If you want your program to use these files later, just save their directory in a variable before running your script. Here is an example :

OUTDIR=$PWD
./script.sh 1> output.log 2> error.log
# Whatever you want to do else ...
echo The output file : =======
cat $OUTDIR/output.log
echo =========================
echo 
echo The errors file : =======
cat $OUTDIR/error.log
echo =========================
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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