Evan Ward
Evan Ward

Reputation: 1439

Bash for loop showing unwanted files/directories

I'm trying to run a simple loop over some local git branches, but whenever I run the loop and echo the lines, I'm seeing it echo all of the files/directories in my current working directory. I don't have much bash experience so I'm confused why the outputs would be different.

git branch --merged

shows me what I expect, only branches.

for l in $( git branch --merged ); do echo $l; done

This is first showing all of the files/directories and then the branches, which I do not want to iterate over.

Upvotes: 0

Views: 67

Answers (2)

John Kugelman
John Kugelman

Reputation: 361869

* will get expanded as a glob. To avoid this you need to quote the expansion of $l.

# Partial fix
for l in $(git branch --merged); do echo "$l"; done

Wait, that doesn't work. You also need to avoid $(...) being subject to glob expansion, which is trickier. To do that you could (temporarily) disable globbing:

# Works, but clumsy
set -o noglob
for l in $(git branch --merged); do echo "$l"; done

Not ideal: it prints * and master on separate lines. It also changes a global option that affects other commands. Better to leave shell options alone and use a while read loop instead.

# Best
while IFS= read -r l; do
    echo "$l"
done < <(git branch --merged)

There are two tricky bits here. One is using while read; do ...; done < file to read lines from a file. The syntax is weird but it applies the < file redirection to the entire loop. The other bit is using <(...) process substitution to use the output of git branch --merged where a filename is normally expected.

Upvotes: 3

virullius
virullius

Reputation: 979

The current branch is marked with a *, this is being interpreted as a pattern that matches all files (expect those starting with .). Two options I see right away are:

  1. Change the Internal Field Separator to newline only.

    IFS='
    '
    for l in $(git branch --merged); do echo $l; done
    
  2. Remove the * from the result.

    for l in $(git branch --merged | tr -d '*'); do echo $l; done
    

Upvotes: 0

Related Questions