[BASH] Getopts/shift within a function, unexpected behaviour


 
Thread Tools Search this Thread
Top Forums UNIX for Advanced & Expert Users [BASH] Getopts/shift within a function, unexpected behaviour
# 1  
Old 04-17-2015
[BASH] Getopts/shift within a function, unexpected behaviour

Hello Gurus Smilie

I'm "currently" (for the last ~2weeks) writing a script to build ffmpeg with some features from scratch.
This said, there are quite a few features, libs, to be downloaded, compiled and installed, so figured, writing functions for some default tasks might help.
Specialy since this is quite a task to achieve, one want to have it reproducable, right?

Also, i wanted to have seperate log files for each lib, instead of everything on the screen.
So i've put that handling into those functions.

Anyway, the issue is, that on some occasions the functions get 2 args, but shifts one eventhough it should not. (to my understand at least)

So my main question is:
Why does the first variable of the 'faac default-download' become deleted/shifted?

Code segment:
The first blocks are just to compare.
Code:
#
# 	Audio
#
	tui-title "Download & compiling dependencies.."
	
	# http://www.linuxfromscratch.org/blfs/view/svn/multimedia/lame.html
	default_download libmp3lame "$URL_libmp3lame"
	default_build    libmp3lame
	tui-bgjob "$TMP" "Building libmp3lame..." "Built libmp3lame."
	
	# http://www.linuxfromscratch.org/blfs/view/svn/multimedia/libogg.html
	default_download libogg "$URL_libogg"
	default_build  libogg
	tui-bgjob "$TMP" "Building libogg..." "Built libogg."
	
	# http://www.linuxfromscratch.org/blfs/view/svn/multimedia/opus.html
#	default_git libopus "$GIT_libopus"
#	autoreconf -fiv  1>>"$LOG_DIR/libopus.log" 2>>"$LOG_DIR/libopus.log"
#	default_build -c libopus
#	tui-bgjob "$TMP" "Building libopus..." "Built libopus."
	
	# http://www.linuxfromscratch.org/blfs/view/svn/multimedia/fdk-aac.html
	default_git libfdk_aac "$GIT_libfdk_aac"
	./autogen.sh 1>>"$LOG_DIR/libfdk_aac.log" 2>>"$LOG_DIR/libfdk_aac.log"
	default_build -c libfdk_aac
	tui-bgjob "$TMP" "Building libfdk_aac..." "Built libfdk_aac."
	
	# http://www.linuxfromscratch.org/blfs/view/svn/multimedia/faac.html
	set -x
	default_download faac "$URL_faac"
	default_build -c faac 
	tui-bgjob "$TMP" "Building faac..." "Built faac."

Functions (related):
Code:
	function default_download() { # [-p PATH -f FILENAME] NAME URL
	# -f NAME, renames basename of url to name
	# -p PATH, changes to this path rathen than to tarball without extension
		URL="" ; PFAD="" ; TARBALL="" ; DATEI="" ; doPfad=false ; doFile=false
		while getopts "p:f:" opt
		do	case "$opt" in
			p)	PFAD="$OPTARG"	# german for PATH, so i dont overwrite that global env var.
				doPfad=true		;;
			f)	TARBALL="$OPTARG"
				doFile=true		;;
			esac
		done
echo "$# $*"
		shift $(( $OPTIND - 1 ))
echo "$# $*"
		[ -z "$1" ] && \
			tui-printf -S 1 "Error, no name passed!" && \
			return 1
		[ -z "$2" ] && \
			tui-printf -S 1 "Error, no URL found..." && \
			return 1
		LOG_THIS="$LOG_DIR/$1.log"
		URL="$2"
		[ -z "$TARBALL" ] && \
			TARBALL="${URL##*/}"
		[ -z "$PFAD" ] && \
			PFAD="${TARBALL/.tar*/}"
		
		if [ -f "$TARBALL" ] || [ -d "$1" ] || [ -d "$PFAD" ]
		then	doLog "$1: Skiping download"
			tui-status 4 "Skiping download"
		else	doLog "$1: Downloading from $URL"
			tui-download "$URL"
			$doFile && tui-mv "${URL##*/}" "$TARBALL"
			doLog "$1: Downloaded to $TARBALL"
			tui-tar -x "$TARBALL"
			doLog "$1: Extracted $TARBALL"
		fi
		cd "$PFAD"
		doLog "$1: Entering ./$PFAD"
	}
	function default_build() { # PKG_STRING ["CONFIG_OPTS"]
	# Builds a package with default behaviour
	# -c, makes distclean
		distclean=false
		while getopts "c" opt
		do	case "$opt" in
			c)	distclean=true		;;
			esac
		done
		shift $(( $OPTIND - 1 ))
		this="$1" ; shift
		LOG_THIS="$LOG_DIR/$this.log"
		[ $# -gt 0 ] && \
			doLog "$this: ./configure .. + ${@}" 
		
		cat > "$TMP" <<-EOF
		PKG_CONFIG_PATH=$PKG_CONFIG_PATH \\
		 	./configure \\
		 		--prefix="$PREFIX" --bindir=$DIR_BIN --libdir=$DIR_LIB --includedir=$DIR_INC --sysconfdir=$CHROOT/etc \\
		 		--disable-static --enable-shared  ${@} 2>>"$LOG_THIS" 1>>"$LOG_THIS"
		
		doLog "$1: Starting make..."
		make V=1			2>>"$LOG_THIS" 1>>"$LOG_THIS"
		doLog "$1: make exit with \$?"
		
		sudo make install		2>>"$LOG_THIS" 1>>"$LOG_THIS"
		RET=\$?
		doLog "$1: make install exit with \$RET"
		
		$distclean && make distclean	2>>"$LOG_THIS" 1>>"$LOG_THIS"
		cd "$DIR_SRC"
		>> "$LOG"
		exit \$RET
		EOF
	}
	export -f doLog
	export -f default_download
	export -f default_git
	export -f default_build

Outputs:
Code:
# | Sea's custom ffmpeg build (0.8)                                                          2015-04-17 16:25:33 | #
# | Found: /home/sea/net/dls/ffmpeg_sources                                                             [  √   ] | #
# | Found: /home/sea/.local                                                                             [  √   ] | #
# | Found: /home/sea/.local/logs                                                                        [  √   ] | #
# |                                     Download & compiling dependencies..                                      | #
2 libmp3lame http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz
2 libmp3lame http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz
# | Skiping download                                                                                    [  »   ] | #
# | Built libmp3lame.                                                                                   [  √   ] | #
2 libogg http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz
2 libogg http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz
# | Skiping download                                                                                    [  »   ] | #
# | Built libogg.                                                                                       [  √   ] | #
# | Built libfdk_aac.                                                                                   [  √   ] | #
+ default_download faac http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2
+ URL=
+ PFAD=
+ TARBALL=
+ DATEI=
+ doPfad=false
+ doFile=false
+ getopts p:f: opt
+ echo '2 faac http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2'
2 faac http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2
+ shift 1
+ echo '1 http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2'
1 http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2
+ '[' -z http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2 ']'
+ '[' -z '' ']'
+ tui-printf -S 1 'Error, no URL found...'
# | Error, no URL found...                                                                              [  ✘   ] | #
+ return 1
+ default_build -c faac
+ distclean=false
+ getopts c opt
+ shift 1
+ this=faac
+ shift
+ LOG_THIS=/home/sea/.local/logs/faac.log
+ '[' 0 -gt 0 ']'
+ cat
+ tui-bgjob /home/sea/.local/logs/command.sh 'Building faac...' 'Built faac.'
# | Building faac...

Obviously aborted the build, since it will fail with the URL as (temp-)file name and missing the very same URL mainwhile...

Any ideas please?
Thank you in advance!
# 2  
Old 04-17-2015
Don't use OPTIND unless getopt actually finds anything. I bet you're using the OPTIND from a previous function call, unchanged.

Last edited by Corona688; 04-17-2015 at 12:26 PM..
This User Gave Thanks to Corona688 For This Post:
# 3  
Old 04-17-2015
So you are saying, i should first catch the total number of arguments passed, and only if it exceeds 2 use OPTIND?
Doesnt it get 'refilled'/'reset' at each function call (or while getopts ...) anyway?

I now have:
Code:
[ $# -gt 2 ] && shift $(( $OPTIND - 1 ))

Seems to fix the issue.

But in NO script i have the shift OPTIND with a condition combined, why do i need when its within a function?
I just dont get it.

Thank you
# 4  
Old 04-17-2015
getopts sets OPTIND when it finds an argument. What happens when it finds no arguments? It doesn't change OPTIND at all. And you are using it for multiple sets of arguments...

Code:
                OPTIND=5 # garbage value leftover from things done earlier

                while getopts "p:f:" opt
		do	case "$opt" in
			p)	PFAD="$OPTARG"	# german for PATH, so i dont overwrite that global env var.
				doPfad=true		;;
			f)	TARBALL="$OPTARG"
				doFile=true		;;
			esac
		done

                shift $(( $OPTIND - 1 ))

...which means that 5, or whatever it happened to be, slips straight through the loop and eats some of your arguments.

Probably the best way to fix it would be to set OPTIND=1 at the top of your functions.

Last edited by Corona688; 04-17-2015 at 06:07 PM..
This User Gave Thanks to Corona688 For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

[BASH] Using getopts

Heyas Just recently there was a thread about parsing arguments, where i read the first time about getopts. This said, i'd like to 'provide' a list function that can be 'trigered' using an 'option'(?). The regarding code snippets are: while getopts... (7 Replies)
Discussion started by: sea
7 Replies

2. Shell Programming and Scripting

Getopts inside a function is not working

Hi All, I am using geopts inside a function in shell script. But it is doesnt seem to read the input args and I always gt empty value in o/p. my code is http://sparshmail.ad.infosys.com/owa/14.2.318.4/themes/base/pgrs-sm.gif This message has not been sent. #!/bin/ksh IFS=' '... (1 Reply)
Discussion started by: prasperl
1 Replies

3. UNIX for Dummies Questions & Answers

Unexpected Behaviour from grepping Text File

Hi! I recently downloaded a wordlist file called 2of12.txt, which is a wordlist of common words, part of the 12dicts package. I've been getting unexpected results from grepping it, such as getting no matches when clearly there ought to be, or returns that are simply wrong. Par exemple: egrep... (4 Replies)
Discussion started by: sudon't
4 Replies

4. UNIX for Dummies Questions & Answers

mtime unexpected behaviour

Hi All, My requirement is to remove the more than 60 days files from Archive folder, so prepared this command. for files in `find /abc/Archive/<file_name_25032012.dat> -type f -mtime 61|xargs ls -lrt` do rm -f $files done I tested this command in both unix and informatica. In unix if files... (8 Replies)
Discussion started by: harris
8 Replies

5. Shell Programming and Scripting

bash:getopts command help

How can I say one of the options is required? can I use an if statement? let say: while getopts ":c:u:fp" opt; do case $opt in c) echo "-c was triggered, Parameter: $OPTARG" >&2;; u) echo "-u was triggered, Parameter: $OPTARG" >&2;; f) echo "-u was triggered,... (2 Replies)
Discussion started by: bashily
2 Replies

6. Shell Programming and Scripting

getopts function in Perl

Hi All I have searches getopts function in Perl a lot, but yet i didn't cleared with it. First I want to know what is the meaning of getopts('t:c:', \%options); and please explain getopts function in an easy way.. (4 Replies)
Discussion started by: parthmittal2007
4 Replies

7. AIX

Unexpected Behaviour with WPAR

Hello, We have a system running AIX 6.1.7.1. We have created a Workload Partition(wpar) on this system with wpar specific routing enabled. On wpar, we are running DNS (UDP/53) and syslog (UDP/514). en0: 1.1.1.1/255.255.255.0 NOT assigned to any wpar en1:... (0 Replies)
Discussion started by: 03sep2011
0 Replies

8. Shell Programming and Scripting

ksh function getopts get leading underscore unless preceded by hyphen

If I call my function with grouped options: "logm -TDIWEFO 'message' ", then only the "T" gets parsed correctly. The subsequent values returned have underscores prefixed to the value: "_D", "_I", etc. If I "logm -T -DIWEFO 'message' ", the "T" and the "D" are OK, but "I" through "O" get the... (2 Replies)
Discussion started by: kchriste
2 Replies

9. UNIX for Dummies Questions & Answers

Function Recursion Shift Problem

Hi, I'm trying to create a script that will display the contents of the users directories, but i'm confused about how to incorporate the shift properly. The problem I'm getting with my script is that it goes throught the first couple of directories but then returns an error as it loses the... (10 Replies)
Discussion started by: nuvpal
10 Replies

10. Shell Programming and Scripting

ksh: can you use getopts in a function?

I wrote a script that uses getopts and it works fine. However, I would like to put the function in that script in a startup file (.kshrc or .profile). I took the "main" portion of the script and made it a function in the startup script. I source the startup script but it doesn't seem to parse... (4 Replies)
Discussion started by: lyonsd
4 Replies
Login or Register to Ask a Question