4

I am calling find from a perl script like this:

    my $one_file = `find $search_dir -name "\*.$refinfilebase.search" -print | head -n 1`;

If I execute it from the shell, I get no error. Also, it returns the right value to $one_file, but I get this on the prompt:

find: write error: Broken pipe

Why would that be? How can I get rid of this find: write error: Broken pipe message?

719016
  • 9,922
  • 20
  • 85
  • 158
  • Try executing it from shell, does same error appear? – Alexandr Ciornii Jul 07 '11 at 10:32
  • edited: if I execute it from the shell, I get no error. Also, it returns the right value when called from Perl, but I always get the error prompt. – 719016 Jul 07 '11 at 11:14
  • 1
    This might be of help: [How to detect whether “find” found any matches?](http://unix.stackexchange.com/questions/13860/how-to-detect-whether-find-found-any-matches) Note the possible use of `-quit` instead of `head -n 1` and the mention of the `head` buffer filling up. – Mike Jul 07 '11 at 11:35

3 Answers3

4

This "error" is perfectly normal and is to be expected.

  • You're running a find command which prints out (potentially) many lines of output.
  • You're feeding that into head which quits after getting one line of input.
  • The find command tries to write its remaining lines to a pipe that has no one listening anymore (head is dead).
  • find will throw an error.

If you want to get rid of the error just do:

my $file = `find .... 2>/dev/null | head -n 1`;

This will keep the utterly predictable error from find from getting to your terminal (since neither the backticks nor the pipe into head touch stderr, which is where that error is being printed).

unpythonic
  • 4,020
  • 19
  • 20
  • While my answer answers your actual question, the answer by @TLP points you in the correct direction. There's certainly no reason to spawn off three extra processes (shell, find, head) if you can do it directly in your script. You're also less vulnerable to hacks since you wouldn't be running a shell with one of your variables just dropped into it (e.g. let `$refinfilebase = '"; rm -rf /; "echo '`) – unpythonic Jul 07 '11 at 13:42
3

Why are you using find and head in backticks, when there are perl ways to handle it? I.e.:

I would only recommend using backticks when you're absolutely sure about what you are doing, and it seems to me that you are not. Heck, you could make your current attempt work by simply doing this:

my @files = `find $search_dir -name "\*.$refinfilebase.search" -print`
my $one_file = $files[0];
TLP
  • 66,756
  • 10
  • 92
  • 149
  • what is the method that will work with the oldest perl version possible? Diamond operator? – 719016 Jul 07 '11 at 14:19
  • @avi For that, you will need to ask a new question. I like opendir myself. – TLP Jul 07 '11 at 16:36
  • done, thanks http://stackoverflow.com/questions/6614085/finding-many-thousands-of-files-in-a-directory-pattern-in-perl – 719016 Jul 07 '11 at 16:44
1

You could try this (although I did not manage to reproduce your error message using the code you posted, so perhaps this error-free version of mine might give you an error message as well...):

my $file = `find $search_dir -name "\*.ssf" -print -exec head -n 1 {} \\;`;

Here's some sample output I got from a test run:

./tmp1.ssf
HEADER    PROTEIN                                 21-FEB-11     1PDB

HTH

canavanin
  • 2,559
  • 3
  • 25
  • 36