0

I am trying to learn bash and I did a one liner like such:

for f in *; do echo $f; done

This prints the all the file name in current directory.

Output:

a file
testfile

Since f is able to grab "a file" just fine, then I would do something like this:

for f in *; do
    if [ -f ${f} ]; then
       LINE=$(wc -l < $f)
       WORD=$(wc -c < $f)
       echo $f ${LINE} ${WORD}
    fi
done

This script failed at line 4 because "a file" has space in them.

What I need help with: Why does it fail?

F is able to grab the filename properley. Intuitively, i would believe that -f ${f} would be able to check if "a file" is a file.

Why does that "a file" passed the for loop but failed at the if statement check?

ZpfSysn
  • 807
  • 2
  • 12
  • 30
  • 3
    You need to quote `$f` every where in each command. – anubhava Oct 11 '19 at 22:05
  • 3
    Expanding the commandline is not done recursive, but only once. When `*` is expanded in filenames, these names are not split again on spaces. When you use `$f` in the loop the commandline is expanded again. Use quotes in the loop. – Walter A Oct 11 '19 at 22:13
  • 3
    Shell syntax has a lot of sharp edges like this; I recommend [shellcheck.net](https://www.shellcheck.net) for pointing out common problems/mistakes. – Gordon Davisson Oct 11 '19 at 22:16

1 Answers1

2

You need to (double) quote each reference of $f so that bash knows the 'a' and 'file' are not separate objects, eg:

for f in *; do
    if [ -f "${f}" ]; then
       LINE=$(wc -l < "${f}")
       WORD=$(wc -c < "${f}")
       echo "${f}" ${LINE} ${WORD}
    fi
done
markp-fuso
  • 28,790
  • 4
  • 16
  • 36