Skip to main content
replaced http://unix.stackexchange.com/ with https://unix.stackexchange.com/
Source Link

Unquoted variables and command substitutions like $i or $(git …) apply the split+glob operatorsplit+glob operator to the string result. That is:

  1. Build a string containing the value of the variable or the output of the command (minus final newlines in the latter case).
  2. Split the string into separate fields according to the value of IFS.
  3. Interpret each field as a wildcard pattern and replace it by the list of matching file names; if a pattern doesn't match any file, leave it intact.

The output of git branch | grep -v master (step 1) contains * master which is split (step 2) into two fields * and master; * is replaced (step 3) by the list of file names in the current directory.

You can run set -f to temporarily disable globbing. Another approach is to avoid command substitution and instead parse the input with readparse the input with read. Neither do the right thing though — you'll have spurious branch names, because the git output contains more than what you need (the * flag to indicate the current branch, but also things like remotes/somewhere/foo -> bar for remote-tracking branches). I think the following is safe if inelegant:

for i in $(git branch | sed -e 's/^..//' -e 's/ .*//'); do
   echo $i
done

I think the robust way is to use git-for-each-ref.

for i in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes); do
  echo $i
done

Unquoted variables and command substitutions like $i or $(git …) apply the split+glob operator to the string result. That is:

  1. Build a string containing the value of the variable or the output of the command (minus final newlines in the latter case).
  2. Split the string into separate fields according to the value of IFS.
  3. Interpret each field as a wildcard pattern and replace it by the list of matching file names; if a pattern doesn't match any file, leave it intact.

The output of git branch | grep -v master (step 1) contains * master which is split (step 2) into two fields * and master; * is replaced (step 3) by the list of file names in the current directory.

You can run set -f to temporarily disable globbing. Another approach is to avoid command substitution and instead parse the input with read. Neither do the right thing though — you'll have spurious branch names, because the git output contains more than what you need (the * flag to indicate the current branch, but also things like remotes/somewhere/foo -> bar for remote-tracking branches). I think the following is safe if inelegant:

for i in $(git branch | sed -e 's/^..//' -e 's/ .*//'); do
   echo $i
done

I think the robust way is to use git-for-each-ref.

for i in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes); do
  echo $i
done

Unquoted variables and command substitutions like $i or $(git …) apply the split+glob operator to the string result. That is:

  1. Build a string containing the value of the variable or the output of the command (minus final newlines in the latter case).
  2. Split the string into separate fields according to the value of IFS.
  3. Interpret each field as a wildcard pattern and replace it by the list of matching file names; if a pattern doesn't match any file, leave it intact.

The output of git branch | grep -v master (step 1) contains * master which is split (step 2) into two fields * and master; * is replaced (step 3) by the list of file names in the current directory.

You can run set -f to temporarily disable globbing. Another approach is to avoid command substitution and instead parse the input with read. Neither do the right thing though — you'll have spurious branch names, because the git output contains more than what you need (the * flag to indicate the current branch, but also things like remotes/somewhere/foo -> bar for remote-tracking branches). I think the following is safe if inelegant:

for i in $(git branch | sed -e 's/^..//' -e 's/ .*//'); do
   echo $i
done

I think the robust way is to use git-for-each-ref.

for i in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes); do
  echo $i
done
Source Link
Gilles 'SO- stop being evil'
  • 865.3k
  • 205
  • 1.8k
  • 2.3k

Unquoted variables and command substitutions like $i or $(git …) apply the split+glob operator to the string result. That is:

  1. Build a string containing the value of the variable or the output of the command (minus final newlines in the latter case).
  2. Split the string into separate fields according to the value of IFS.
  3. Interpret each field as a wildcard pattern and replace it by the list of matching file names; if a pattern doesn't match any file, leave it intact.

The output of git branch | grep -v master (step 1) contains * master which is split (step 2) into two fields * and master; * is replaced (step 3) by the list of file names in the current directory.

You can run set -f to temporarily disable globbing. Another approach is to avoid command substitution and instead parse the input with read. Neither do the right thing though — you'll have spurious branch names, because the git output contains more than what you need (the * flag to indicate the current branch, but also things like remotes/somewhere/foo -> bar for remote-tracking branches). I think the following is safe if inelegant:

for i in $(git branch | sed -e 's/^..//' -e 's/ .*//'); do
   echo $i
done

I think the robust way is to use git-for-each-ref.

for i in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes); do
  echo $i
done