LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 11-28-2010, 01:55 AM   #1
Rahil Parikh
LQ Newbie
 
Registered: Nov 2010
Posts: 15

Rep: Reputation: 0
Unhappy Problem while writing Shell Script


Hello,

I am new to writing shell scripts. So, please bare with me. I am currently trying to write a shell script which will read the directory path as input from user and will traverse the Dir tree to find all available audio and video files. I have tried to write as much as I could but I don't know where I am making mistake as I get some files to be audio file which are actully tar balls. On the second note there are some files which video but script shows them to be audio. And, some video files are completely skipped. I am giving the shell script below so that you can see. I am using two external files as source which I am attaching.

Code:
#!/bin/bash

#Let's load the extensions that we want to search for
vdExt=$(cat vdExtList)
adExt=$(cat adExtList)

#Clearing screen won't hurt
clear

#Now let' start with real stuff
echo "Enter starting directory : "
read initDir

#Get qualified paths for all files & dirs
dirTree=$(find $initDir -print)

for dirTreeEntry in $dirTree
do
	#Check if dirTreeEntry is a file
	timeToExit=0
	if [ -f $dirTreeEntry ]
	then
		#Get file name and convert it to lowercase for further string comparision
		fileName=$(basename $dirTreeEntry | tr [:upper:] [:lower:])
		
		#Ittrate through video extensions and if filename has
		#desired extension then we have found our file so now
		#it's time to skip to next file
		for ext in $vdExt
		do
			if [ $(echo $fileName | grep "$ext") ]
			then
				echo "$dirTreeEntry is a video file."
				timeToExit=1
				break;
			fi
				
			#We have already found out video file so we need not
			#search for audio file. It's safe to skip audio file
			#search.
			if [ $timeToExit -eq 1 ]
			then
				timeToExit=0
				break
			fi
		done
		
		#Ittrate through audio extensions and if filename has
		#desired extension then we have found our file so now
		#it's time to skip to next file
		for ext in $adExt
		do
			if [ $(echo $fileName | grep "$ext") ]
			then
				echo "$dirTreeEntry is an audio file."
				timeToExit=1
				break;
			fi
				
			if [ $timeToExit -eq 1 ]
			then
				timeToExit=0
				break
			fi
		done
	fi
done
exit 0
So, I would request someone to inspect my script and help me understand what is my mistake.

Thank you,
Rahil
Attached Files
File Type: txt adExtList.txt (3.7 KB, 8 views)
File Type: txt vdExtList.txt (1.4 KB, 5 views)
File Type: txt Shell.sh.txt (826 Bytes, 5 views)

Last edited by Rahil Parikh; 11-28-2010 at 02:07 AM. Reason: Added Comment for Better Understanding
 
Old 11-28-2010, 05:19 AM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,944
Blog Entries: 54

Rep: Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731
First of all well done for providing your script. That really helps. You do not need to load up your ExtLists (just 'grep' them), you don't need to iterate through 'dirTreeEntry in $dirTree' (make 'find' find only files), iterating over extensions isn't efficient either ('grep') and you don't need lower case ('grep -i'):

Code:
#!/bin/bash
# ExtLists location:
LISTPATH=/dev/shm
echo "Enter starting directory : "
read initDir

find $initDir -type f -printf "%p\n" 2>/dev/null| while read ITEM; do
	EXT="${ITEM//*./}"
	if [ ${#EXT} -ne 0 ]; then
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/vdExtList && echo "${ITEM} has video"
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/adExtList && echo "${ITEM} has audio"
	else
		file "${ITEM}" 2>/dev/null|grep -qi video && echo "${ITEM} has video"
		file "${ITEM}" 2>/dev/null|grep -qi audio && echo "${ITEM} has audio"
	fi
done
exit 0
...however extensions are not a hard requirement and file has a finite database, so:

Code:
#!/bin/bash
echo "Enter starting directory : "
read initDir

find $initDir -type f -printf "%p\n" 2>/dev/null| while read ITEM; do
	RESULT=$(ffmpeg -vframes 1 -ss 00:01:00 -i "${ITEM:=item}" 2>&1| grep 'Stream.*[Au|Vi]')
	VIDEO="${RESULT//Video: /}"; AUDIO="${RESULT//Audio: /}"; 
	[ ${#VIDEO} -ne ${#RESULT} && echo "${ITEM} has video"
	[ ${#AUDIO} -ne ${#RESULT} && echo "${ITEM} has audio"
done
exit 0
may provide a more accurate method.

Last edited by unSpawn; 11-28-2010 at 01:39 PM. Reason: //stray escapes removed
 
Old 11-28-2010, 10:35 AM   #3
Rahil Parikh
LQ Newbie
 
Registered: Nov 2010
Posts: 15

Original Poster
Rep: Reputation: 0
Smile

Hey unSpawn,

Thank you very very much for such a quick reply. I saw what you wrote in the script but I am new to writing the scripts. So, the script you wrote seems to be pretty complex to me and I am unable to break it into pieces to understand. For that reason, I would like to request you to explain how the script works and I would be interested in learning the style/method behind it so that I can improve.

Thank you,
Rahil

Quote:
Originally Posted by unSpawn View Post
First of all well done for providing your script. That really helps. You do not need to load up your ExtLists (just 'grep' them), you don't need to iterate through 'dirTreeEntry in $dirTree' (make 'find' find only files), iterating over extensions isn't efficient either ('grep') and you don't need lower case ('grep -i'):

Code:
#!/bin/bash
# ExtLists location:
LISTPATH=/dev/shm
echo "Enter starting directory : "
read initDir

find $initDir -type f -printf "\%p"\"\n" 2>/dev/null| while read ITEM; do
	EXT="${ITEM//*./}"
	if [ ${#EXT} -ne 0 ]; then
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/vdExtList && echo "${ITEM} has video"
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/adExtList && echo "${ITEM} has audio"
	else
		file "${ITEM}" 2>/dev/null|grep -qi video && echo "${ITEM} has video"
		file "${ITEM}" 2>/dev/null|grep -qi audio && echo "${ITEM} has audio"
	fi
done
exit 0
...however extensions are not a hard requirement and file has a finite database, so:

Code:
#!/bin/bash
echo "Enter starting directory : "
read initDir

find $initDir -type f -printf "\%p"\"\n" 2>/dev/null| while read ITEM; do
	RESULT=$(ffmpeg -vframes 1 -ss 00:01:00 -i "${ITEM:=item}" 2>&1| grep 'Stream.*[Au|Vi]')
	VIDEO="${RESULT//Video: /}"; AUDIO="${RESULT//Audio: /}"; 
	[ ${#VIDEO} -ne ${#RESULT} && echo "${ITEM} has video"
	[ ${#AUDIO} -ne ${#RESULT} && echo "${ITEM} has audio"
done
exit 0
may provide a more accurate method.
 
Old 11-28-2010, 02:05 PM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,944
Blog Entries: 54

Rep: Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731
Post

Quote:
Originally Posted by Rahil Parikh View Post
I would be interested in learning the style/method behind it
None really. Reading and just doing mostly.


Quote:
Originally Posted by Rahil Parikh View Post
explain how the script works
OK

Code:
# Use find to look for files only and always print the full path and item name with a newline and read it into variable ITEM
find $initDir -type f -printf "%p\n" 2>/dev/null| while read ITEM; do
        # Strip down ITEM to the last dot to get the "extension" in variable EXT
        # Try this on the CLI to see what I mean: '/bin/bash; set -vx; ITEM=/sbin/.metallica-jump_in_the_fire.aac; eval echo "${ITEM//*./}";'
	EXT="${ITEM//*./}"
        # Count amount of chars ('man test') to see if the variable holds something. String comparison is not needed.
	if [ ${#EXT} -ne 0 ]; then
                # If EXT isn't empty then
                # grep ${LISTPATH}/?dExtList for a line starting (^) with a literal dot (\.) and
                # the extension string quitly (-q) and finding only one match (speed).
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/vdExtList && echo "${ITEM} has video"
		grep -qim1 "^\.${EXT}$" ${LISTPATH}/adExtList && echo "${ITEM} has audio"
	else
                # If EXT is empty then try running 'file' on ITEM and grep for a case-insensitive string
		file "${ITEM}" 2>/dev/null|grep -qi video && echo "${ITEM} has video"
		file "${ITEM}" 2>/dev/null|grep -qi audio && echo "${ITEM} has audio"
	fi
done
exit 0
Code:
# basically the same as above except here you determine the result using one tool: ffmpeg.
        # Store the result of running 'ffmpeg' on ITEM in variable RESULT and grep for a string that matches either
        # "Stream:.*Audio" or "Stream:.*Video". Speed up ffmpeg processing by extracting only one frame and limited time.
	RESULT=$(ffmpeg -vframes 1 -ss 00:01:00 -i "${ITEM:=item}" 2>&1| grep 'Stream.*[Au|Vi]')
        # Subtract the literal string "Video:" from RESULT into variable VIDEO and the same for Audio.
	VIDEO="${RESULT//Video: /}"; AUDIO="${RESULT//Audio: /}"; 
        # So if the amount of chars in the variable VIDEO does not match RESULT then ITEM must contain video stream.
	[ ${#VIDEO} -ne ${#RESULT} && echo "${ITEM} has video"
	[ ${#AUDIO} -ne ${#RESULT} && echo "${ITEM} has audio"
 
1 members found this post helpful.
Old 11-29-2010, 03:48 PM   #5
Rahil Parikh
LQ Newbie
 
Registered: Nov 2010
Posts: 15

Original Poster
Rep: Reputation: 0
Thanks unSpawn! That script worked like a gem! It gave me really hard time to understand but I got it almost. I have some doubts which I want to ask you.

Like,
Code:
find $initDir -type f -printf "%p\n" 2>/dev/null| while read ITEM; do
When does the printf gets executed?

Code:
grep -qim1 "^\.${EXT}$" ${LISTPATH}/vdExtList && echo "${ITEM} may be video."
How does echo know that now that the grep has found the extension and it's time to print to STDOUT?
 
Old 11-29-2010, 06:04 PM   #6
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,944
Blog Entries: 54

Rep: Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731Reputation: 2731
Quote:
Originally Posted by Rahil Parikh View Post
When does the printf gets executed?
Printing items is executed as part of the 'find' command.


Code:
grep -qim1 "^\.${EXT}$" ${LISTPATH}/vdExtList && echo "${ITEM} may be video."
How does echo know that now that the grep has found the extension and it's time to print to STDOUT?[/QUOTE]
The return value in variable "$?" (try '/bin/true; echo $?; /bin/false; echo $?;') tells the shell what to do.

Using "&&" could be translated as
Code:
if [ $? -eq 0 ]; then
 echo "${ITEM} may be video."
fi
or
Code:
case "$?" in
 0)  echo "${ITEM} may be video."
 ;;
esac
Here are some scripting guides that might come in handy:
http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
http://www.tldp.org/LDP/Bash-Beginne...tml/index.html
http://www.tldp.org/LDP/abs/html/
 
  


Reply

Tags
directory, programing, shell script, shell scripting, traversal


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


Similar Threads
Thread Thread Starter Forum Replies Last Post
writing a shell script icecubeflower Linux - Newbie 1 03-29-2009 01:16 PM
Help writing a shell script! smoothdogg00 Programming 5 04-26-2006 11:15 AM
[SOLVED] Writing a shell script mattz40 Debian 5 04-13-2005 06:56 PM
shell script writing ust Linux - General 6 01-24-2005 01:06 PM
help writing shell script np complete Linux - Newbie 6 08-30-2004 09:43 PM


All times are GMT -5. The time now is 09:23 PM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration