variables in find command and more shell problem
Solution 1
You need to take care of several things
double 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="$SAVEIFS"
Don't use reserved words as variable names (avoid
for
let
etc. Avoid also many "common" variable names, ieLINES
,COLUMNS
, etc.why aliasing
export
toexport
? 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 ansh
subshell: any variables you declare in there will be lost once that sh exits out to the invoking shell.
You need something like:
#!/bin/bash
for 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|while
done #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
.
Solution 2
As per comment (converting *.3gp to *.mp3):
for n in *.3gp; do
ffmpeg -y -i "$n" "${n%.3gp}.mp3"
done
As per olivier's comment, to also act on files in subdirectories, *.3gp
can be replaced with $(find ...)
, provided the filenames don't need escaping (namely they don't contain whitespace or globbing characters \[?*
). Alternatively **/*.3gp
can be used (in bash, put shopt -s extglob
in your .bashrc
).
Related videos on Youtube
PersianGulf
My God is Allah and my religious book is Quran.Up to now my life was based on my God's will and whatever I gained or lost is due to my God's want. My aspiration is to put my life in favour of my lord, Allah since I believe this would be a desirable life. I am a fan and supporter of Free Software and i do all my computer works based on Freesoftware. My other interests are Linux/GNU family and BSD. My main speciality is network administration but I also have decent knowledge in C/C++ and Python progmming. In general I love programming languages. My favorite sport is mountain climbing because I love outdoors and generaly I'm a nature lover. I truely love to increase my knowledge because I'm eager to know as much as possible. Not only I have this desire for myself, but also for every human being and I will do my best to help anyone who wishes to be on this path. (You can find everythinf about me at http://pahlevanzadeh.net)
Updated on September 18, 2022Comments
-
PersianGulf over 1 year
Possible Duplicate:
Recursive rename files and directoriesI wrote the following script:
#!/bin/bash SAVEIFS=$IFS alias 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 $IFS unalias export IFS=$SAVEIFS
Problem:
You know when more one shell you can't export your variable in other shell, So i need to :
use variables
don't use run shell
So, 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 directory
I tested it with export or delete export or let , i discovered -exec has problem with built-in shell command....!
Do you have any idea????
-
Admin over 11 yearsCan you sum up what you want to accomplish with your script? What's the input and the desired output?
-
PersianGulf over 11 yearsMy input set of *.3gp files, and i convert them to *.mp3 files, in first step of script i wrote successfully, but when i convert, suppose i do have myfile.3gp and when i convert it renamed to myfile.3gp.mp3 , i used expr for solve it.
-
Olivier Dulac over 11 yearsneat approach. easy to read, and nice handling of the spaces in filenames. A caveat: won't find the 3gp file in the subdirs. Actually it find them in "the current dir, and only the first level" instead of "all files underneath directory $1" as @Mohsen Pahlevanzadeh apparently intended...
-
peterph over 11 years@OlivierDulac good point :)
-
Gilles 'SO- stop being evil' over 11 years
while IFS= read -r line
has come up several times, I think Why iswhile IFS= read
used so often, instead ofIFS=; while read..
? is our definitive post on the subject. I haven't reviewed your script fully. These are good explanations. The script is still more complex and brittle than it needs to be, in particular the call tosed
should be replaced by built-in shell constructs:myfilewithoutext=${wholeline#.3gp}
. -
Olivier Dulac over 11 years@Gilles: I use bash versions that are so old they can't handle those "fancy" constructs ^^ . I try to keep it portable (albeit, I agree, at the expense of sometimes having to do some ugly hacks). Thanks for the reformatting, I'll edit again to weed out old stuff (like my questions about the extension, which were answered by other comments)
-
Gilles 'SO- stop being evil' over 11 yearsAFAIR bash has always supported
${…#…}
and friends. It's in POSIX. Most Bourne shells don't have it, but systems without a POSIX shells are getting far and few. -
Olivier Dulac over 11 yearsThanks for that heads-up, I'll have a look to see if our system's bash supports it. But it's old (version 2.0.something) (no "$LINENO", no "$BASH_SOURCE", etc...)
-
Gilles 'SO- stop being evil' over 11 years
${VAR#PREFIX}
was already supported in bash 1.14. I can't easily find information about earlier versions. In BSD, it seems to have appeared only in 4.4BSD, so some time during the FreeBSD-2.x/NetBSD-1.x series (according to the manpages). -
nino over 8 yearsfor a script to fire the ffmpeg, it's recommend to add
< /dev/null
to the end of the ffmpeg command line. You need the script to "push" the execution to ffmpeg without hanging.