Don't use 'ls' in shell scripts... why?
Long long ago in a thread far away, I remember one of the LQ gurus recommending that 'ls' should not be used for programmatic purposes. There were several justifications given.
I've used this as a rule of thumb ever since... but I don't remember why... I can see it in a case like this, where launching 'ls' would spawn a separate process... Code:
for i in *.txt Am I imagining this? |
You never should parse `ls` output if you are not the only who is going to use the script. People make aliases in example with `-F` flag which appends extra characters. Your script will simply be broken.
|
|
Quote:
Funny thing is that I knew 90% of what was there... I just couldn't articulate it. Good to have it one place. |
Quote:
|
My take on the matter is that it relies on the consistent behavior, over time, of another application. As soon as that behavior changes, which happens often enough, then your script breaks. Add to that, that it is simply wasteful, when bash already has the facility to access the filesystem and it's structure. Why add one or more extra steps that, at best, serve only to get in the way?
--- rod. |
Quote:
In terms of having the behaviour of the program change... that's why there are standards. Sticking with standards compliant behaviour should ensure that you get the same thing every time. |
I think I understand where you are coming from but maybe next time you should pick a better example:
Code:
$ ls -r -d |
I don't think differences in versions are the main reason; if that was the case, people would recommend against sed, find, ps, tar, etc. The two main reasons I can think of are:
PS In case it wasn't clear, this is one vote for "it's fine to use ls in a script." ls -l is a different story, though. |
Quote:
|
Quote:
|
Quote:
is trivial for bash to provide. I also agree in part with ta0kira that using ls on its own may not necessarily be dangerous, assuming that the following portion: Quote:
try to steer clear of using it at all. |
Quote:
|
Quote:
Weird file names are nearly not as rare as one might think. You can create one very easily by accident, for example typing Code:
touch Isn't it cool? Code:
Isnt it cool? Code:
cool. Code:
shopt -s nullglob Code:
shopt -s nullglob The shopt -s nullglob tells Bash that non-matching glob patterns expand to nothing; the default is to expand to the pattern itself. It is enough (and a good practice) to set it once at the start of the script. (To be honest, I always forget it, and end up testing if FILE exists within the loop..) I normally use Code:
LANG=C LC_ALL=C It is the safest and most robust way I know of. If you need to compute something and yield it to the script outside the loop, you should use Code:
LANG=C LC_ALL=C While you can technically do a recursive directory walk in Bash, it is nigh impossible to do safely, because parent directory names may change mid-walk. find won't get confused by that; you only may see file names that are no longer there. Note: I haven't used the Bash 4 **/ notation David the H. mentions below. It should work just as well as find does I think, as long as you set the proper Bash shell options. |
Bash from version 4 up has a new globstar feature for recursive globbing.
Code:
shopt -s globstar #it's not enabled by default. Of course you'll still need to use find for more advanced matches, such as by mtime. |
All times are GMT -5. The time now is 01:02 PM. |