[SOLVED] Having trouble combining a for loop with find
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am trying to get a listing of all non-directories of the form *.h or *.C or *.cc or *.cpp, and then iterate over that collection to do some work on those files. Here is my code:
Code:
for x in find `pwd` ! -type d -name '*.h' -o -name '*.C' -o -name '*.cc' -o -name '*.cpp'
do
#some work with $x
done
I tried globbing in one string for the name, but it doesn't seem to work. Aside from that, this combination doesn't seem to work either. I would appreciate your help! Note: this is part of my solution to a programming assignment in bash scripting.
Either way does the same thing in the end, really, although the while-read loop seems to be much more popular for some reason. A for loop reads the input a "word" at a time, while read grabs whole lines by default.
Whichever one you use, you should first make sure that input list is being generated correctly, then ensure that the loop is processing them properly. I usually do this by simply echoing the variable back, like this:
Code:
while read x; do
echo "$x" | cat -A
done < <( list_generating_command ) #or <file
Piping things through cat -A is useful in cases where there's a chance of unwanted trailing spaces or non-printing characters appearing in the field. It can help you to spot dos-style carriage returns when working on text files that may have been produced on a Windows machine, for example, or where tabs have been used instead of spaces.
Once you know the basic loop is working, you can replace it with the commands you want.
PS: Don't forget that find also has an -exec option, which is useful when you only have to run a single command on the files it finds.
Either way does the same thing in the end, really, although the while-read loop seems to be much more popular for some reason.
For var in (command substitution) were popular for a very long time before until some time when some people started showing while read from pipe commands. In those days people were still conservative about anything that's not compatible with the original sh.
I am trying to get a listing of all non-directories of the form *.h or *.C or *.cc or *.cpp, and then iterate over that collection to do some work on those files. Here is my code:
Code:
for x in find `pwd` ! -type d -name '*.h' -o -name '*.C' -o -name '*.cc' -o -name '*.cpp'
do
#some work with $x
done
don't do it this way. you are going to encounter error when file names have spaces. Then you will have to set provision for IFS and such. With a while read loop, you don't need to change IFS unnecessarily.
Of course, if your task is simple, using -exec of find will just do.
Code:
find ..... | while read -r file
do
# echo do something with "$file"
done
find ..... | while read -r file
do
# echo do something with "$file"
done
In some shells the while block is placed inside a subshell so sometimes the "while read; do :; done < <()" method is better. e.g. if a data like a counter is required to be manipulated inside the loop and then also referred in the next statements after it, that data may be lost after the loop.
Certainly and also not compatible with the original sh. It is obvious and intended to be only compatible with bash i.e. I've also said something in post #5 about people being conservative with compatibility among shells.
will be "find", "`pwd`", "!", "-type", etc. That is, the loop sees your command as a list of words. What you need to do is embed the command.
Code:
for x in $( find . ! -type etc....)
Also, `pwd` is completely unnecessary here. Just use . or perhaps $PWD. And unless you're using a really old shell, $(..) is recommended over `..`
Thanks for your reply! The first tip you gave seems to work just fine. I know that $ is for de-referencing a variable, but I would have never though to use it like this. Could you explain briefly why this works?
Thanks! And thank you everyone for your kind replies, I will be sure to incorporate your comments into my test cases!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.