Gregg
Gregg

Reputation: 532

Difference between variable assignments

I had a question that was answered here: https://unix.stackexchange.com/questions/264925/awk-fs-with-back-slashes

After that I tried adding it to a .sh script that starts with:

#!/bin/bash

My Line:

category1Filenames=(\`find . -maxdepth 1 -type f |
gawk 'BEGIN { FS = "(\\\\./)|(\\\\.)" } ; { print $2 }' | sort -u\`)

And then I print the output using:

for genericFilename in ${category1Filenames[@]}; do  
  printf "%s\n" $genericFilename  
done 

But this gives me the error:

gawk: cmd. line:1: warning: escape sequence `\.' treated as plain `.'

If I change the line to be:

category1Filenames=$(find . -maxdepth 1 -type f |
gawk 'BEGIN { FS = "(\\\\./)|(\\\\.)" } ; { print $2 }' | sort -u)

Then it works as expected.

I'm assuming that the problem was with using the back tick characters, but I don't understand why. Probably because I don't understand the behavior of ` vs ' vs ". If anyone can point me to documentation that can explain this behavior (maybe tldp) then it would be greatly appreciated.

Upvotes: 1

Views: 124

Answers (2)

chepner
chepner

Reputation: 531858

Instead of find, just iterate over all the files in the current directory, and use the shell to process only regular files and extract the file name.

for name in *; do
    [[ -f $name ]] || continue
    name_only=${name%%.*}
    printf "%s\n" "$name_only"
done

Upvotes: 1

Rany Albeg Wein
Rany Albeg Wein

Reputation: 3474

The backquote (`) is used in the old-style command substitution, The foo=$(command) syntax is recommended instead. Backslash handling inside $() is less surprising, and $() is easier to nest. See BashFAQ82

Using backquotes, you'll have to escape required sequence for gawk:

category1Filenames=(`find . -maxdepth 1 -type f | gawk 'BEGIN { FS = "(\\\./)|(\\\.)" } ; { print $2 }' | sort -u`)

Aside: Feed categoryFilenames array in a loop instead:

while read -r line; do
    categoryFilenames+=("$line")
done < <(find . -maxdepth 1 -type f | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print $2 }' | sort -u)

Now it is safer to iterate over categoryFilenames like you did, but with double-quotes:

for genericFilename in "${category1Filenames[@]}"; do  
  printf "%s\n" "$genericFilename"  
done  

Don't forget to "Double quote" every literal that contains spaces/metacharacters and every expansion: "$var", "$(command "$var")", "${array[@]}", "a & b".

Upvotes: 1

Related Questions