FrenchKheldar
FrenchKheldar

Reputation: 485

Difference between using ls and find to loop over files in a bash script

I'm not sure I understand exactly why:

for f in `find . -name "strain_flame_00*.dat"`; do
   echo $f
   mybase=`basename $f .dat`
   echo $mybase
done

works and:

for f in `ls strain_flame_00*.dat`; do
   echo $f
   mybase=`basename $f .dat`
   echo $mybase
done

does not, i.e. the filename does not get stripped of the suffix. I think it's because what comes out of ls is formatted differently but I'm not sure. I even tried to put eval in front of ls...

Upvotes: 4

Views: 20278

Answers (3)

glenn jackman
glenn jackman

Reputation: 246807

The correct way to iterate over filenames here would be

for f in strain_flame_00*.dat; do
   echo "$f"
   mybase=$(basename "$f" .dat)
   echo "$mybase"
done

Using for with a glob pattern, and then quoting all references to the filename is the safest way to use filenames that may have whitespace.

Upvotes: 13

sampson-chen
sampson-chen

Reputation: 47267

Another difference that hasn't been mentioned yet is that find is recursive search by default, whereas ls is not. (even though both can be told to do recursive / non-recursive through options; and find can be told to recurse up to a specified depth)

And, as others have mentioned, if it can be achieved by globbing, you should avoid using either.

Upvotes: 2

John Greene
John Greene

Reputation: 131

First of all, never parse the output of the ls command.

If you MUST use ls and you DON'T know what ls alias is out there, then do this:

(
COLUMNS=
LANG=
NLSPATH=
GLOBIGNORE=
LS_COLORS=
TZ=
unset ls
for f in `ls -1 strain_flame_00*.dat`; do
  echo $f
  mybase=`basename $f .dat`
  echo $mybase
done
)

It is surrounded by parenthesis to protect existing environment, aliases and shell variables.

Various environment names were NUKED (as ls does look those up).

One unalias command (self-explanatory).

One unset command (again, protection against scrupulous over-lording 'ls' function).

Now, you can see why NOT to use the 'ls'.

Upvotes: 4

Related Questions