I use multiple GitHub accounts at work, so I need to modify the remote url to add my work account. I have figured out the recursive find -execdir, and how to get/sed/set the remote url, but I cannot combine them.

I tested the find command using git st, and it works correctly:

find . -type d -name ".git" -execdir zsh -c "git st" \;

I tested the git set process, and that works correctly:

git remote set-url origin $(git remote get-url origin | sed 's|https://github|https://my_work_username@github|g')" \

When I combine them, it isn't working so well:

find . -type d -name ".git" -execdir zsh -c "git remote set-url origin $(git remote get-url origin | sed 's|https://github|https://my_work_username@github|g')" \;

I first get an error that there is no .git folder and than a bunch of git syntax errors:

fatal: not a git repository (or any of the parent directories): .git usage: git remote set-url [--push] [] or: git remote set-url --add or: git remote set-url --delete

If I add an echo, I find that the git command I am issuing is:

git remote set-url origin

with no parameter

I've run out of ideas for trouble-shooting or term for searching to figure this one out.

  • @ilkkachu Thank you for providing the right amount of information. You should get credit for the correct answer, if you want. If not, I will add the solution and accept my own answer. Commented Feb 16 at 23:29
  • 1
    Regarding the statement I have removed from the question: I'm fine with ilkkachu's answer receiving all the credit. Commented Feb 17 at 16:38

1 Answer 1

find . ... -execdir zsh -c "git remote get-url origin $(git ...)" \;

Here, the command substitution is inside a double-quoted string, and so is expanded in the main shell, before find runs. Then it runs in the wrong directory, leading to the error. If you enable set -x and run the command, you should see a constant string there in the zsh -c command line.

Like so:

$ set -x
$ find . -type d -execdir bash -c "echo $RANDOM" \;
+ find . -type d -execdir bash -c 'echo 22924' ';'

You'll need to use single quotes to protect the expansions so the inner shell sees them and gets to process them.

$ find . -type d -execdir bash -c 'echo $RANDOM' \;
+ find . -type d -execdir bash -c 'echo $RANDOM' ';'

I think you can mostly just flip the single and double quotes around here since the sed command doesn't contain anything that necessarily needs to be within single quotes:

find . -type d -name ".git" -execdir \
   zsh -c 'git remote set-url origin "$(
               git remote get-url origin | 
               sed "s|https://github|https://my_work_username@github|g"
           )"' \;

(For completeness, also put double quotes around the command substitution to prevent word splitting in the inner shell command. Not that the URLs here are likely to contain whitespace or glob characters, but it's good practice.)

If the sed command had something like $ in it, and you needed to put single quotes within a single-quoted string, you'd have do uglier escaping like 'it isn'\''t so', or just split the command in multiple files which often works as an easy workaround for quoting issues.

You must log in to answer this question.

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