quickshiftin
quickshiftin

Reputation: 69711

Confusing error from | xargs sed

I have a little find-replace utility around git. Let's ignore suggestions for a different approach ATM. I'm really trying to understand this error from sed. Take a look at the command

function git_find_replace
{
    local grepexp="$1"
    local replace="$2"

    # build sed command
    local sedcmd="s/$grepexp/$replace/g"

    # First find the files; then pipe through xargs sed for replacement
    git grep --name-only "$grepexp" | xargs sed -r "$sedcmd" -i ''
}

The command works, and I get the expected results, however, when I run this on one of my repositories, I get an error from sed

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

But the git component returns a set of files that all exist (slightly mangled for sake of post)

git grep --name-only 0.46.1
release/a.html
release/resources/javascript/a.js
release/resources/version
release/index.html
release/installer.html

I've verified the existence of these files manually with ls. For example, if I change the xargs component to this

git grep --name-only 0.46.1 | xargs ls -l

There are no complaints from ls about missing files or directories. So why do I get an error from sed?

Update

To save you some digging through the answers and comments, this turned out to be a difference between BSD and GNU versions of sed. See this thread for more.

Upvotes: 2

Views: 2060

Answers (3)

John Kugelman
John Kugelman

Reputation: 361977

If you pass an extension to sed -i, it needs to be adjoined to the -i, as in sed -i.bak myfile. It can't be a separate argument. sed -i .bak myfile would cause sed to do in place editing of files named .bak and myfile.

When you write sed -i '' sed tries to do in place editing on a file whose name is the empty string.

If you don't want backup files made, just leave off the argument entirely. No ''.

git grep --name-only "$grepexp" | xargs sed -r "$sedcmd" -i

Upvotes: 4

Barmar
Barmar

Reputation: 782130

This isn't really an answer, it's a debugging step, but it's too long to put in a comment. Try creating a script called print_args:

#!/bin/bash
i=1
for arg
do
    printf "Arg %d = '%s'\n" $i "$arg"
    ((i++))
done

Then try:

git grep --name-only "$grepexp" | xargs ./print_args sed -r "$sedcmd" -i ''

This should show all the arguments being passed to sed, you may see something that explains why sed is parsing it incorrectly.

Upvotes: 2

DopeGhoti
DopeGhoti

Reputation: 767

sed may be complaining because you are using the s/foo/bar/ command on values of $foo and/or $bar that may contain the delimiter -- /. Try s%foo%bar/ or s@foo@bar or some other delimiter you're confident will not appear.

Upvotes: -2

Related Questions