Possible Duplicate:Recursive rename files and directories I wrote the following script:#!/bin/bashSAVEIFS=$IFSalias export='export'IFS=$(echo -en \n\b)          find $1 -name * -a -type f -exec sh -c let  len=`expr length {}` \;  -exec  sh -c let  str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {}  $str.mp3 \;# restore $IFSunalias exportIFS=$SAVEIFSProblem:You know when more one shell you can't export your variable in other shell, So i need to :use variablesdon't use run shellSo, how  i do it?When run the following script:find $1 -name * -a -type f -exec let  len=`expr length {}` \;  -exec let  str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {}  $str.mp3 \; # Note : above script doesn't has 'sh -c' I get the following error:find: `let': No such file or directoryI tested it with export or delete export or let , i discovered -exec has problem with built-in shell command....!Do you have any idea????
variables in find command and more shell problem
shell;find;quoting
You need to take care of several thingsdouble quotes to protect the content of a variable from shell interpretation. IFS contain probably by default space+tab+newline, so : NEWIFS=IFS is probably going to end up putting nothing in NEWIFS.SAVEIFS=$IFS...IFS=$(echo -en \n\b)   #yes, you can have  inside $( ... ) : the shell will gladly interpret them by# order of depth inside the $() construct. # A big advantage over using backquotes where it would get mixed up and almost unreadable...IFS=$SAVEIFSDon't use reserved words as variable names (avoid for let etc. Avoid also many common variable names, ie LINES, COLUMNS, etc.why aliasing export to export? looks like a good way to create a loop if the shell is old, or at best it's useless.precising -name * means you avoid any filename or dirnames starting with a ..-exec sh ....  will launch it in an  sh subshell: any variables you declare in there will be lost once that sh exits out to the invoking shell.You need something like: #!/bin/bashfor adirectory in $@ ; do    find $adirectory -type f -name '*.3gp' -print | while IFS= read -r wholeline ; do       mylength=$(echo $wholeline | wc -c)  #Not needed, just kept as exemple of a way to achieve it       myfilewithoutext=$(echo $wholeline | sed -e 's/.3gp$//' )            #keeps only the filename without its .3gp or .3GP extension.       ffmpeg -y -i $wholeline  ${myfilewithoutext}.mp3 > /dev/null   #?  please check if it works    done #end of the find|whiledone #end of the for looping on all the arguments passed to the script (dir names)IFS in that while IFS= read -r wholeline ; do   will be set to the empty string ONLY during the invocation of the read -r wholeline. Untouched outside of it.    VAR=something command parameters will invoke command parameters, with the value of VAR temporarily set to something. Here we set IFS to '', i.e. nothing. It will still be passed line by line, and as IFS is empty the whole line ends up read by read wholeline. 