Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
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.
Sure,
I seem to remember reading somehting about the way that bash interpets a line. I guess a way of telling bash to read the brackets as part of the commands rather than to enclose another command. er, thats why.
If you have bash version 4 or higher, then here's a solution that doesn't require find or any other outside tool. It should also work fine with any unusual filename characters, as it relies only on simple shell globbing.
Code:
#!/bin/bash
shopt -s dotglob globstar
files=( ./** )
for file in "${files[@]}" ; do
path="${file%/*}"
name="${file##*/}"
if [[ ! -f $file || ! $name == .* ]] ; then
echo "skipping $file"
continue
else
mv "$file" "$path/${name#.}"
fi
done
exit 0
Sure,
I seem to remember reading somehting about the way that bash interpets a line. I guess a way of telling bash to read the brackets as part of the commands rather than to enclose another command. er, thats why.
Except that grail's question was about why you want to do this in the first place. Parentheses in find are only needed to group expressions together to enforce precedence. In this case it appears you simply want both tests to be evaluated equally, so they are unnecessary. Just use...
But to answer your actual question, $(..) is a subshell. Simply treat everything inside it as if it were on a separate line.
Code:
for f in $( find /media/music/ -depth \( -name "*.m4a" -o -name "*.wma \) )
Also note that $((..)) is a separate operator that expands arithmetical expressions.
Finally, it may have been mentioned before, but a for loop is not recommended when the input is from a command that generates filenames or other strings that can include spaces. This is because for reads each word as a separate input, and can't distinguish lexical whitespace from syntactical whitespace (at least not without futzing about with IFS).
Use a while+read loop instead, with process substitution for input. Since read works on a per-line basis, rather than per-word, each line from find will be safely accepted as the complete filename that it is (barring the unlikely possibility of encountering a filename that itself contains a newline character).
Code:
while read f ; do
your commands
done < <( find /media/music/ -depth -name "*.m4a" -o -name "*.wma" )
Last edited by David the H.; 07-31-2011 at 12:42 AM.
Reason: fixd a cupla typos
Except that grail's question was about why you want to do this in the first place. Parentheses in find are only needed to group expressions together to enforce precedence. In this case it appears you simply want both tests to be evaluated equally, so they are unnecessary. Just use...
But to answer your actual question, $(..) is a subshell. Simply treat everything inside it as if it were on a separate line.
Code:
for f in $( find /media/music/ -depth \( -name "*.m4a" -o -name "*.wma \) )
Also note that $((..)) is a separate operator that expands arithmetical expressions.
Finally, it may have been mentioned before, but a for loop is not recommended when the input is from a command that generates filenames or other strings that can include spaces. This is because for reads each word as a separate input, and can't distinguish lexical whitespace from syntactical whitespace (at least not without futzing about with IFS).
Use a while+read loop instead, with process substitution for input. Since read works on a per-line basis, rather than per-word, each line from find will be safely accepted as the complete filename that it is (barring the unlikely possibility of encountering a filename that itself contains a newline character).
Code:
while read f ; do
your commands
done < <( find /media/music/ -depth -name "*.m4a" -o -name "*.wma" )
Wow, thanks you so much. That makes things a lil easier for me to wrap my head around. Could you point me to a book that would be linear in how it goes through bash? I have looked at the bash cook book and it leaves me spun around a little bit. Nominal Animal posted the wiki link for gaining a better grasp of regex ( thanks). Any ways, thanks guys. I have a new job which I will be using bash much more. This is all very helpful.
Definitely read the first one at least. It covers in fair detail all the basic concepts you need to know. Follow sublinks too; the whole site is a treasure trove of bash info.
Speaking of which, I need to retract something from my last post. After writing it, I came across their find tutorial, and it seems that parenthetical grouping can be more important than I had thought (see section 10).
Speaking of which, I need to retract something from my last post. After writing it, I came across their find tutorial, and it seems that parenthetical grouping can be more important than I had thought (see section 10).
Don't beat yourself up too hard on this one David as the current example given would not have fallen prey to the issue
mentioned here. In saying that, thanks for the find as I did not know that detail before
Nah, I'm not "beating myself up" over it. There's always something new to learn, after all, and that sometimes means unlearning wrong stuff too.
I'm mostly just keeping myself honest, and trying to avoid giving bad advice. While the specific example above isn't affected, it would only take a small modification, such as adding an -exec command, to make it vitally important.
It might be a little hacky but it successfully renames hidden files and folders within your current directory to not be hidden(unfortunately it doesn't currently work recursively).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.