[SOLVED] Bash help needed: How to recursively browse subfolders in a for loop?
Linux - GeneralThis 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
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.
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
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?
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.
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?
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.
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.
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
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.