LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This 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


Reply
  Search this Thread
Old 07-30-2011, 08:55 PM   #16
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,996

Rep: Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187

Could you explain why you feel the brackets are necessary?
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 07-30-2011, 10:23 PM   #17
mrmnemo
Member
 
Registered: Aug 2009
Distribution: linux
Posts: 527

Original Poster
Rep: Reputation: 51
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.
 
Old 07-30-2011, 11:24 PM   #18
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
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
 
1 members found this post helpful.
Old 07-31-2011, 12:37 AM   #19
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Quote:
Originally Posted by mrmnemo View Post
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...
Code:
find /media/music/ -depth -name "*.m4a" -o -name "*.wma
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
 
1 members found this post helpful.
Old 07-31-2011, 11:02 PM   #20
mrmnemo
Member
 
Registered: Aug 2009
Distribution: linux
Posts: 527

Original Poster
Rep: Reputation: 51
Smile

Quote:
Originally Posted by David the H. View Post
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...
Code:
find /media/music/ -depth -name "*.m4a" -o -name "*.wma
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.

Ollie
 
Old 07-31-2011, 11:46 PM   #21
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,342

Rep: Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746Reputation: 2746
Some good links for bash
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/
 
1 members found this post helpful.
Old 08-01-2011, 09:19 AM   #22
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
This is my usual list of bash scripting references:

http://mywiki.wooledge.org/BashGuide
http://www.linuxcommand.org/index.php
http://mywiki.wooledge.org/BashFAQ
http://mywiki.wooledge.org/BashPitfalls
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/index.html
http://www.gnu.org/software/bash/manual/bashref.html
http://wiki.bash-hackers.org/start

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).

http://mywiki.wooledge.org/UsingFind
 
1 members found this post helpful.
Old 08-01-2011, 10:02 AM   #23
mrmnemo
Member
 
Registered: Aug 2009
Distribution: linux
Posts: 527

Original Poster
Rep: Reputation: 51
@chrism01 and David the H : bookmarked and scanned real fast. Thanks for taking the time to post that guys.
 
Old 08-01-2011, 07:03 PM   #24
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,996

Rep: Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187
Quote:
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
 
Old 08-02-2011, 07:03 AM   #25
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
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.
 
Old 08-02-2011, 05:40 PM   #26
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,996

Rep: Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187
True enough
 
Old 09-17-2012, 05:20 AM   #27
isoneguy
LQ Newbie
 
Registered: Sep 2012
Posts: 1

Rep: Reputation: Disabled
I wasn't able to get any of these previous resolutions to work in CentOS.

With a little digging I came to this conclusion:

find ./ -depth -name '.*' -exec bash -c 'mv {} $(echo {} | cut -c 4-)' \;

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).
 
  


Reply

Tags
bash sed find


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Recursively rename some files mail4mz Programming 21 07-15-2011 10:18 AM
script to rename files recursively rs232 Linux - General 3 05-08-2011 02:05 PM
[SOLVED] how to rename files recursively, only keeping last x digits plus extension furryspider Programming 2 11-29-2009 12:55 PM
Copying hidden files recursively? mrd Linux - General 1 09-30-2005 07:51 AM
How to recursively rename files using their directory name pattern ceg4048 Linux - General 2 09-28-2005 01:16 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 09:54 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration