I'm trying to run a command to remove require_once from php files from here (code below), but I am getting the error:

sed: can't read -: No such file or directory

I am in the correct folder; what's the problem?

find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
  -not -wholename '*/Application.php' -print0 | \
  xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'


If I run:

find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
  -not -wholename '*/Application.php' -print0

I get:

find: invalid predicate `-wholename'

I tried this and it returned a list of all the files:

find . -name '*.php' -not -name '*/Loader/Autoloader.php' \
  -not -name '*/Application.php' -print0

But then changing the original to reflect this:

find . -name '*.php' -not -name '*/Loader/Autoloader.php' \
  -not -name '*/Application.php' -print0 | \ xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'

Gives the error:

-bash: xargs: command not found

FYI, I'm running sed version 4.1.2 and I'm a bit a lost in the command line already, so please explain answers

  • 2
    Works for me. Replace "xargs -0 sed" with "xargs -0 echo sed". What's the output of that? Nov 11, 2010 at 16:18
  • Can't get past the -bash: xargs: command not found error
    – Ashley
    Nov 11, 2010 at 17:36
  • 1
    The -bash: xargs: command not found error is because of the backslash immediately before xargs. If you remove the backslash or if there's a newline after the backslash, it should work. Nov 11, 2010 at 22:31
  • @ Dennis, make that an answer and it's all yours. Worked a charm
    – Ashley
    Nov 11, 2010 at 22:42
  • 1
    Why are you piping find to xargs can't -exec do it for you? maybe read this question Nov 12, 2010 at 13:58

5 Answers 5


The error seems to indicate that sed tries to read from stdin. Have you tried just the find part to see if it returns any file?

  • 1
    If I modify the -wholename to -name it works (without the rest of the code)
    – Ashley
    Nov 11, 2010 at 17:37

Your second invocation doesn't make any sense, why the "\ " before the xarsg? You try to call a program called " xargs", and bash tells you it can't find it (note the double blank after the colon), which is hardly surprising.

To get rid of the error case where sed hangs when xargs returns zero files (because it's trying to read from stdin when there are no command line arguments), you should add -r to your xargs arguments.

  • It's from the Zend Framework docs, I didn't write it (and wouldn't know how)
    – Ashley
    Nov 12, 2010 at 21:41

What version of sed do you have? POSIX sed doesn't understand double-dash options, neither does minised, but GNU sed does.

For something more portable (and IMO nicer), try sed -i '/require_once/s![[:space:]]*!&// !'.

  • I don't think sed -i is any more portable than sed --in-place, it's a GNU extension anyway. FreeBSD also has it, but the suffix argument is compulsory, to you have to write sed -i .bak or sed -i ''. Nov 11, 2010 at 16:42
  • sed v4.1.2, please see question for update
    – Ashley
    Nov 11, 2010 at 17:35

I prefer perl -pi.bak for these sorts of cases.

FMTYEWTK at http://www.perl.com/pub/2004/10/14/file_editing.html

(FMTYEWTK stands for Far More Than You Ever Wanted To Know)


Unfortunately, the page that the question links to has gone away, so I can't check the original command. Instead, I will do some guessing.

The first error comes from running GNU sed and doing in-place editing on a input file called -. This file does not exist and you get that error:

Example (using an empty sed script):

$ sed -i -e '' -
sed: can't read -: No such file or directory

Where the - filename comes from, I don't know, but it could have something to do with not getting any filenames from find (see below).

You then seem to have switched to some other machine or find implementation, because now the find command no longer recognize the -wholename test. This error confuses me.

You then change -wholename to -name, but you should have changed it to -path as -wholename is the same as -path in GNU find.

Your find command still won't work, even if you change -wholename to -path since the expression you use should be a regular expression.

As a regular expression, */Application.php matches the exact string */Application.php. A * at the start of a regular expression matches a literal *. You might have meant to use .*/Application.php, but this would have been the same as -name "Application.php".

Taking all of the above into consideration, and removing the xargs call (that error comes from escaping the space in front of the command name, which then becomes part of the actual command name, which can't be found):

find . -type f -name '*.php' \
    ! -path '.*/Loader/Autoloader.php' \
    ! -name 'Application.php' \
    -exec sed -i 's/require_once/\/\/ &/' {} +

This also slims down the call to GNU sed a bit so that it doesn't need to use extended regular expressions.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .