LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 02-19-2010, 12:44 PM   #1
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Rep: Reputation: 1
Bash help needed: How to recursively browse subfolders in a for loop?


Hi,
I wrote a script for copying mp3 files to my girlfriend's mp3-player and it looks like this:

Code:
mount /dev/sdc /test -o sync
for i in *.mp3; do 
  cp $i /test/Musik/newalbum; 
  sleep 5; 
done;
This is the only way to make the player see the files in the correct order and it finally works! (after toying with rsync and timestamps in vain) Thus, the 5 seconds pause after each copy is necessary to make sure the player's internal controller did really write the file, so I cannot use xcopy or rsync.

So, I have to go to the album folder on my hd and call the script, and the album is transfered to the player. So far so good.

But I want the script to browse subfolders also, something like this (pseudo code
Code:
for dir=all_sub_folders; do
  mkdir /test/Musik/$dir
  for i in *.mp3; do 
    cp $i /test/Musik/$dir; 
    sleep 5; 
  done;
done;
How do I realize that (dir=all_sub_folders) in bash?

Last edited by frisil; 02-20-2010 at 12:09 AM. Reason: problem solved
 
Old 02-19-2010, 12:48 PM   #2
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 552Reputation: 552Reputation: 552Reputation: 552Reputation: 552Reputation: 552
Rather than using the for--do--done loop to find all the files, why not either use:

1) `find` -- which will recursively enter subfolders automatically, or
2) just use the -R switch on your `cp` command, to copy recursively?

Note that both these methods do not create your new subdirs, so you'd need to add some code to create those subdirs first; maybe do a preliminary `find` operation first, to identify all subdir names, and create them in the target area, and THEN do the `find` recursively for the files themselves, and copy them over to their respective subdirs?
 
Old 02-19-2010, 12:49 PM   #3
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980
Code:
find -d /where/ever | while read DIR
do
  ... something using $DIR...
done
 
1 members found this post helpful.
Old 02-19-2010, 01:09 PM   #4
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
Quote:
Originally Posted by acid_kewpie View Post
Code:
find -d /where/ever | while read DIR
do
  ... something using $DIR...
done
Seems interesting, but does not work. I tried the following for a test:

Code:
#!/bin/sh
find -d /home/bert/00fuertigerplayer | while read DIR
do
echo $DIR found
done
and get the following error:

Code:
find: warning: the -d option is deprecated; please use -depth instead, because the latter is a POSIX-compliant feature.
find: Der Pfad muß vor dem Suchkriterium stehen: /home/bert/00fuertigerplayer
Aufruf: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [Pfad...] [Suchkriterium]
translation: path must be before search criteria

when I use
Code:
#!/bin/sh
find -d | while read DIR
do
echo $DIR found
done
in the correct folder I get every file listed, not just the folders.
 
Old 02-19-2010, 02:27 PM   #5
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
I'm very close now with "for directory in `find . -type d `", but it does not work when there are space in the folder names, and some folders have spaces. I tried:

Code:
for directory in `find . -type d `
do
echo $directory found
done
for a test run and it lists the folders, but goes haywire when foldes have spaces in their names. Like for example:

Code:
./Musik/Dead found
can found
Dance found
./Musik/Dead found
can found
Dance/Serpent's found
Egg found
./Musik/Dead found
can found
Dance/Within found
the found
Realm found
of found
a found
Dying found
Sun found
is what I get from the folder "Dead can Dance" with the subfolders "Serpent's Egg" and "Within the Realm of a Dying Sun".

How do I fix this? Or is there a way to autorename the folders and convert spaces to _ (underscore)? I know krename can do that with filenames, but not with subfolders, or am I wrong?
 
Old 02-19-2010, 03:08 PM   #6
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980Reputation: 1980
ahh pants, yeah, autopilot... meant -type d, sorry.

you should follow the rest of the example though, the while read DIR puts the WHOLE line into the variable, doing it in a for loop there makes each word a seperate value to be iterated over.
 
1 members found this post helpful.
Old 02-19-2010, 03:29 PM   #7
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
Okay, that works, I get things like:

./Musik/Dead can Dance found
./Musik/Dead can Dance/Serpent's Egg found

from my test script

now I need to strip the first "./" from my $directory variable so I can use

Code:
cp "$i" "/test/Musik/$directory"
How do I do this? It should be very easy I guess, but I'm not too experienced with bash.
 
Old 02-19-2010, 04:15 PM   #8
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
much simpler

Code:
cp -R --copy-contents source destination
whizje
 
0 members found this post helpful.
Old 02-19-2010, 04:24 PM   #9
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
Quote:
Originally Posted by whizje View Post
much simpler

Code:
cp -R --copy-contents source destination
whizje
If you'd read my initial post carefully, you'd see why that doesn't work: I need the sleep 5 pause after each copy to make sure the filesystem really syncs. Thus, I cannot use any recursive copy option, I need to script my own one with a 5 seconds delay after each copy. Basically, I'm just trying to rebuild cp -R or rsync -r by hand using bash, so I can get the delay in.
 
Old 02-19-2010, 04:33 PM   #10
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
But to answer your question

Code:
${i#"./"}
This removes ./ from the front of $i and delivers the required $
 
1 members found this post helpful.
Old 02-19-2010, 05:28 PM   #11
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
And here a version wich automaticaly creates subdirs and sleeps 5 seconds after every new creation

Code:
find .  \( \( -name '*.mp3' \) -o ( -type d \) \)-exec sh -c 'cp -R --copy-contents "$@" /home/whiz/test2/;sleep 5' sh {} \;
Copies from the current directory to the directory /home/whiz/test2 in this example and copies the directory tree

whizje

Last edited by whizje; 02-19-2010 at 05:40 PM. Reason: error in last \)
 
Old 02-19-2010, 07:16 PM   #12
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
Wow, that looks advanced! I must honestly say I don't understand it, but I will try it out. Does it pause 5 seconds after each file, too?
 
Old 02-19-2010, 08:12 PM   #13
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by frisil View Post

But I want the script to browse subfolders also, something like this (pseudo code
Code:
for dir=all_sub_folders; do
  mkdir /test/Musik/$dir
  for i in *.mp3; do 
    cp $i /test/Musik/$dir; 
    sleep 5; 
  done;
done;
How do I realize that (dir=all_sub_folders) in bash?
if you have Bash 4.0,something like this

Code:
#!/bin/bash
shopt -s globstar
for dir in **/
do
  echo "directory: $dir"
  #mkdir -p <use $dir>
  for file in $dir/*mp3
  do
     echo "file: $file"
     # do your copy here.
  done
done
 
Old 02-20-2010, 12:08 AM   #14
frisil
LQ Newbie
 
Registered: Feb 2010
Location: behind you ;-)
Distribution: SimplyMepis
Posts: 17

Original Poster
Rep: Reputation: 1
Talking

Thank you all for your ideas! Thisi is what my script looks like now (and it works):

Code:
#!/bin/sh
cd $home/4player
find -type d | while read directory
do
  echo "processing: ${directory#"./"}"
  cd "$home/4player/${directory#"./"}"
  mkdir "/test/Musik/${directory#"./"}"
  for i in *.mp3; do
   cp "$i" "/test/Musik/${directory#"./"}"
   sleep 5
  done
done
crude, but working ;-)
 
  


Reply

Tags
bash, mp3player


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 On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 03:50 AM
Bash loop using output of grep not working as needed Jim Pye Programming 7 01-16-2008 10:27 PM
bash: list recursively directories only kpachopoulos Programming 1 06-18-2007 02:00 AM
Recursively browse graphics on CD from command line ewto Linux - Software 1 03-11-2005 10:04 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 09:39 AM.

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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration