ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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 have a nested while loop (2). so this will go through a parent dir and get the children dirs one at a time then (basically) moving files somewhere else then when finished moving the files, delete prior dir and sub-dir without removing the parent dir before moving on to the next child dir and doing the same. But it just keeps looping until it gets tired then moves on to the next one.
it is at "big" script. do not let that confuse you. as stated it is after processing the files it is just moving them somewhere else then deleting the prior dir structure, leaving the parent.
quick break down: it reads from one dir, process files, copies file to one dir then moves the original file to another dir to have a back up copy. then deletes the dirs they use to be in. then it just keeps looping until "it gets tried or dizzy" before moving on.
script
Code:
#!/bin/bash
#Jun 06, 2017
#all in one
count=0 max=0
working_dir=/media/data/TESTING-MUSIC
move_old_flac=/run/media/userx/3TB-External/OldFlac
move_to=/media/data/MOVED-TESTING-MUSIC
copy_to=/run/media/userx/3TB-External/Copied-Music
final_move=/media/data/Final-move
script_dir=/home/userx/scripts/production
max="$(find "$working_dir" -type f \( -name "*.mp3" -o -name "*.MP3" -o -name "*.flac" \) | wc -l)"
while read FILENAME
do
f=$FILENAME
path=${f%/*}
xfile=${f##*/}
title=${xfile%.*}
ext=${xfile##*.}
while read FILENAME
do
f=$FILENAME
path=${f%/*}
xfile=${f##*/}
title=${xfile%.*}
ext=${xfile##*.}
ARTIST="`exiftool -Artist "$FILENAME" -p '$Artist'`"
TITLE="`exiftool -Title "$FILENAME" -p '$Title'`"
ALBUM="`exiftool -Album "$FILENAME" -p '$Album'`"
GENRE="`exiftool -Genre "$FILENAME" -p '$Genre'`"
TRACK="`exiftool -Track "$FILENAME" -p '$Track'`"
NewFile="$ARTIST-$TITLE.mp3"
#first move to different dir
Moving=${path/$working_dir/$move_to}
mkdir -pv "$Moving"
if [[ "$ext" = 'mp3' ]] ; then
mv -v "$FILENAME" "$Moving/$NewFile"
else
mv -v "$FILENAME" "$Moving"
fi
#to Retag new MP3
retagdir="$script_dir/$NewFile"
if [[ "$ext" == 'flac' ]] ; then
{ #reestablish path to flac and name after move
FLACNAME="$Moving/$title.$ext"
flac -cd "$FLACNAME" | lame -b 320 - "$NewFile"
id3v2 -A "$ALBUM" "$retagdir"
id3v2 -a "$ARTIST" "$retagdir"
id3v2 -t "$TITLE" "$retagdir"
id3v2 -g "$GENRE" "$retagdir"
id3v2 -T "$TRACK" "$retagdir"
#put new mp3 back
path=${FLACNAME%/*}
mv -v "$retagdir" "$path"
OldFlac2Dir=${path/$move_to/$move_old_flac}
mkdir -p "$OldFlac2Dir"
mv -v "$FLACNAME" "$OldFlac2Dir"
}
fi
FILENAME1="$Moving/$NewFile"
if [[ "$ext" = 'mp3' ]] ; then
{
echo "id3v2 start"
#writes name to mp3 tag info
id3v2 -D "$FILENAME1"
id3v2 -a "$ARTIST" "$FILENAME1"
id3v2 -A "$ALBUM" "$FILENAME1"
id3v2 -t "$TITLE" "$FILENAME1"
id3v2 -g "$GENRE" "$FILENAME1"
id3v2 -T "$TRACK" "$FILENAME1"
echo "id3v2 stop"
}
fi
if [[ "$ARTIST" && ! -n "$ALBUM" ]] ; then
{
Catagory="$final_move/$ARTIST"
coping="$copy_to/$ARTIST"
mkdir -pv "$Catagory"
mkdir -pv "$coping"
cp -v "$FILENAME1" "$coping"
mv -v "$FILENAME1" "$Catagory"
}
else
{
Catagory="$final_move/$ARTIST/$ALBUM"
coping="$copy_to/$ARTIST/$ALBUM"
mkdir -pv "$Catagory"
mkdir -pv "$coping"
cp -v "$FILENAME1" "$coping"
mv -v "$FILENAME1" "$Catagory"
}
fi
echo "
MAX is $max
Done is $((++count))
--------
Left $((max - count))
"
[[ $max = $count ]] && break
done< <(find "$path" -type f \( -name "*.mp3" -o -name "*.MP3" -o -name "*.flac" \))
echo;echo
echo "outside Loop1"
echo "path: $path"
echo
#outside Loop1
#path: /media/data/MOVED-TESTING-MUSIC/America/[2004] America - Horse with No Name and Other Hits, A
#gets the parent and plus one dir down.
#should be a better way but brains is not functioning at 100% at this time.
delete1=${path#*/*/*/*/}
delete1=${delete1%%/*}
delete1="$move_to/$delete1"
delete2=${path/$move_to/$working_dir}
delete2=${delete2#*/*/*/*/}
delete2=${delete2%%/*}
delete2="$working_dir/$delete2"
[[ -d "$delete1" ]] && ( rm -rv "$delete1" ; exit)
[[ -d "$delete2" ]] && ( rm -rv "$delete2" ; exit)
done< <(find "$working_dir" -type f \( -name "*.mp3" -o -name "*.MP3" -o -name "*.flac" \))
echo "outside loop"
feedback off of CLI
Code:
'/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/07_i_cant_give_everything_away.mp3' -> '/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David
_Bowie_-_Blackstar-2016-DDS/David Bowie-I Can'\''t Give Everything Away.mp3'
id3v2 start
Stripping id3 tag in "/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/David Bowie-I Can't Give Everything Away.mp3"...id3v1 and v2 stripped.
id3v2 stop
'/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/David Bowie-I Can'\''t Give Everything Away.mp3' -> "/run/media/userx/3TB-External/Copied-Music/David Bowie/Blacksta
r/David Bowie-I Can't Give Everything Away.mp3"
'/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/David Bowie-I Can'\''t Give Everything Away.mp3' -> "/media/data/Final-move/David Bowie/Blackstar/David Bowie-I Can'
t Give Everything Away.mp3"
MAX is 10
Done is 10
--------
Left 0
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
removed directory '/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS'
removed directory '/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar'
removed directory '/media/data/MOVED-TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP'
removed '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/00_david_bowie_-_blackstar-2016-proof.jpg'
removed '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/00_david_bowie_-_blackstar-2016.m3u'
removed '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/00_david_bowie_-_blackstar-2016.nfo'
removed '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS/00_david_bowie_-_blackstar-2016.sfv'
removed directory '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS'
removed directory '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar'
removed '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/★.jpg'
removed directory '/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP'
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
find: ‘/media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS’: No such file or directory
outside Loop1
path: /media/data/TESTING-MUSIC/David Bowie Blackstar [2016] CDRIP/blackstar/David_Bowie_-_Blackstar-2016-DDS
outside loop
userx%voider ⚡ production ⚡>
I've tried the break, and exit as seen in the script but as you can see it just keeps looking.
First off, I only quickly glimpsed at your script, and this is what stood out...
your issue is that parenthesis create a subshell, meaning that your "break" statement gets executed in a completely different shell (same issue with exit, it exits a completely different process than you think). I think that replacing the parenthesis around the break with curly braces will fix your issue.
In any case, the following works :
First off, I only quickly glimpsed at your script, and this is what stood out...
your issue is that parenthesis create a subshell, meaning that your "break" statement gets executed in a completely different shell (same issue with exit, it exits a completely different process than you think). I think that replacing the parenthesis around the break with curly braces will fix your issue.
In any case, the following works :
from what I read that { } curly brackets are the one that creates another sub shell and these do not ( )
It should not even need a break in that loop, I've changed it to a basic if statement and am getting the same results. Next to try is the mindepth and maxdepth trial.
because this is making no since to me. When find is done with one directory it is suppose to move on to the next one. Not keep looking inside of it, especially when it is not there.
I could just run it and not worry about it, because it works in what it is suppose to be doing. Tough it is slightly bugging me as to why it is not doing what I expect it to when finished and dir is deleted.
from what I read that { } curly brackets are the one that creates another sub shell and these do not ( )
I do not know where did you read that. The truth is: () makes subshell, {} just a scope - or something like that.
see man bash:
Code:
(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).
{ list; } list is simply executed in the current shell environment.
Exception: if ( ) is inside an expression and used for grouping.
Quote:
Originally Posted by BW-userx
It should not even need a break in that loop, I've changed it to a basic if statement and am getting the same results.
I have no idea what did you really try and what is the result. You gave no enough information.
Quote:
Originally Posted by BW-userx
I could just run it and not worry about it, because it works in what it is suppose to be doing. Tough it is slightly bugging me as to why it is not doing what I expect it to when finished and dir is deleted.
because what you suppose is not how it really works. Remember, a program will never do what you wish, but what was implemented.
you posted incomplete scripts, hard to say anything about that, but: you may use -iname in find, probably a bit better.
I do not know where did you read that. The truth is: () makes subshell, {} just a scope - or something like that.
see man bash:
Code:
(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).
{ list; } list is simply executed in the current shell environment.
Exception: if ( ) is inside an expression and used for grouping.
yeah I might have gotten that backwards.
Quote:
I have no idea what did you really try and what is the result. You gave no enough information.
because what you suppose is not how it really works. Remember, a program will never do what you wish, but what was implemented.
yeah I know. hence this post requesting help in trying to figure out why the inner loop keeps looping after the dir is deleted.
it has to be something within the find function that it must be keeping a list within itself, and then using that to still search the dir and sub dir until it sees they are not there.
hence it goes though them one at a time if sub directories are present within its search list.
Quote:
you posted incomplete scripts,
no, that is a complete script. the only thing changed is the code outside of the inner loop, besides that it is a complete working script. I posted just two separate ways I tried the delete directory code, in lue of posting the entire script more than once, which is overkill.
Quote:
hard to say anything about that, but: you may use -iname in find, probably a bit better.
iname yeah that will eliminate the MP3 and mp3 needing only one of them. but has nothing to do with this loop question.
find collects the information before starting the loop and did not recognize you removed something during execution. probably -depth can help on this, but not really sure.
find collects the information before starting the loop and did not recognize you removed something during execution. probably -depth can help on this, but not really sure.
yeah that is what I am figuring too, something like that mindepth maxdepth, still tinkering away on it, as I am doing 3 things at once.
Like I stated it works, only that find will keep running not finding anything, so it has nothing to act on, so all that is really taking place is time going by until it gets to the next directory that it can work on is all.
Both loops are fed from a redirected stdout to stdin:
Code:
while
do
while
do
done < $(command2)
done < $(command1)
might be that this causes the confusion? ( I have not known of any scripts that grow tired or dizzy for that matter, and I tried! )
Or... it's the variables that get overwritten; you read into FILENAME variable in both loops; As far as I could tell in the glimpse I took, they are both in the same (sub)shell; hence in the same scope: hence they're overwritten.
Both loops are fed from a redirected stdout to stdin:
Code:
while
do
while
do
done < $(command2)
done < $(command1)
might be that this causes the confusion? ( I have not known of any scripts that grow tired or dizzy for that matter, and I tried! )
Or... it's the variables that get overwritten; you read into FILENAME variable in both loops; As far as I could tell in the glimpse I took, they are both in the same (sub)shell; hence in the same scope: hence they're overwritten.
Yeah now that you mention it, I suppose I'd need to pull the current dir off the outer loop then run it in the inner loop, then delete it when it gets done moving everything out of it, then the other loop should go to next dir. repeat.
Yes, the FILENAME variable is shared.
This is because each while loop is not fed from a pipe find ... | while read ... that would force a sub shell.
Looks risky, but should work here nevertheless, because it is set at the beginning of the loop to the correct value (from the loop's dedicated input stream).
But the whole structure is fishy somehow.
Certainly needs some cleanup.
Why two nested loops at all? find does a recursion already - shouldn't a simple loop go through the hierarchy?
(1) "Use a real programming language." Pick any one you like, then use Bash's #!"shebang" feature to specify which language Bash should invoke to run your script.
(2) In general, I do not recommend altering any directory structure while you are also in the process of running it. Run it first, placing a list of all matching entries into an array. Then, process the array content. Alternate between "building that list" and "consuming it."
(2a) Most "real" programming languages have a ready-to-use directory runner.
Last edited by sundialsvcs; 06-08-2017 at 07:31 PM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.