Saturday, November 12, 2011

Never parse the output of ls, ps, etc... Use globs or find or something else!

It's all in the title!
So, you want to delete all files that end with .back, and (because you read a terrible advanced bash guide) you're tempted to do this:
gniourf@somewhere:~$ for i in `ls *.back`; do rm $i; done
The problem is that this will miserably fail whenever a filename contains a space. (Try it!). Also, the backticks are ugly (but it's not the worse thing here). Instead, do:
gniourf@somewhere:~$ for i in *.back; do rm "$i"; done
(also observe the quotes). You should realize that bash's globs are infinitely better than parsing the output of a program. If you want to use something like this in a script, maybe you should shopt -s nullglob or shopt -s failglob. For example, try:
gniourf@somewhere:~$ echo *hello # assuming that there's no file ending with hello
The output will be something like:
*hello
Because when a glob doesn't match, it is used verbatim. If you want a non-matching glob to expand to nothing, you must set nullglob on thus:
gniourf@somewhere:~$ shopt -s nullglob
Now,
gniourf@somewhere:~$ echo *hello
outputs nothing.
If you want a non-matching glob to generate an error, you must set failglob on thus:
gniourf@somehwere:~$ shopt -s failglob
Now,
gniourf@somewhere:~$ echo *hello
bash: no match: *hello


Cheers!

No comments:

Post a Comment