0

I wrote a shell snippet shown as below:

is_first=t
for f in "$path"/"m*"
do
    printf "%s\n" $f
    printf "%s\n" $is_first

    if [[ "$is_first" = "t" ]]; then
        is_first=f
        printf "%s\n" $is_first
    else
        printf "%s\n" $is_first
    fi

    printf "%s\n" $is_first
done

The output is as follows:

./merge_non-null
./merge_non-null_bak.sh
./merge_non-null.sh
t
f
f

I'm wondering, how did if-else execute in a for loop? It seems it runs only for the first loop, and all skipped afterwards.

Also, why does printf "%s\n" $is_first only executed for for the first loop? The output I expected is (note the sequence). I believe I've missed something. Sorry if it's too stupid.

./merge_non-null
t
f
f
./merge_non-null_bak.sh
f
f
f
./merge_non-null.sh
f
f
f
tripleee
  • 175,061
  • 34
  • 275
  • 318
dehiker
  • 454
  • 1
  • 8
  • 21

1 Answers1

6

Your quoting is incorrect. The "m*" does not get expanded, because it's in double quotes, so you loop over the literal string; and so the loop only executes once. Then you incorrectly omit quotes inside the loop, and so the shell expands the wildcard in the argument to the first printf. Without quotes, printf with this format string prints one line per token in the expanded string; so you get multiple output lines from a single iteration of the loop, from that first printf.

With correct quoting, your script would become

is_first=t
for f in "$path/m"*
do
    printf "%s\n" "$f"
    printf "%s\n" "$is_first"

    if [[ "$is_first" = "t" ]]; then
        is_first=f
        printf "%s\n" "$is_first"
    else
        printf "%s\n" "$is_first"
    fi

    printf "%s\n" "$is_first"
done

See also When to wrap quotes around a shell variable?

Community
  • 1
  • 1
tripleee
  • 175,061
  • 34
  • 275
  • 318