Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove last argument from argument list of shell script (bash)

Tags:

This question concerns a bash script that is run in automator osx. I am using automator actions to get and filter a bunch of file references from the finder. Then I append to that list the name of the parent folder, also via an automator action. Automator then feeds these arguments to an action called "run shell script". I am not sure exactly how automator invokes the script but the argument list looks like this when echoed with: echo "$@"

/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50

In this case path to 3 files and a folder.

In the shell script I launch an application called ripcheckc* with the args passed from automator minus the last argument(the folder) in the list.

I use this to remove the last argument:

_args=( "$@" ) unset _args[${#_args[@]}-1] 

And this is echo $_args:

/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav

Same as before but without the folder.

Now, if I run ripcheckc with "$@" as argument it works (but fails later on because of that last path in the argument list) If I use ${_args[@]} the application will just abort silently. When I echo $@ and _args the output looks identical except for the last argument.

My question is - what is the difference between $@ and $_args that make the first valid input and the second not?

*The application is ripcheckc

I hope my question makes sense.

EDIT: Solved.

like image 658
Nordanfors Avatar asked Dec 05 '13 11:12

Nordanfors


2 Answers

I have used this bash one-liner before

set -- "${@:1:$(($#-1))}" 

It sets the argument list to the current argument list, less the last argument.


How it works:

  • $# is the number of arguments
  • $((...)) is an arithmetic expression, so $(($#-1)) is one less than the number of arguments.
  • ${variable:position:count} is a substring expression: it extracts count characters from variable starting at position. In the special case where variable is @, which means the argument list, it extracts count arguments from the list beginning at position. Here, position is 1 for the first argument and count is one less than the number of arguments worked out previously.
  • set -- arg1...argn sets the argument list to the given arguments

So the end result is that the argument list is replaced with a new list, where the new list is the original list except for the last argument.

like image 58
starfry Avatar answered Sep 22 '22 07:09

starfry


Assuming that you already have an array, you can say:

unset "array[${#array[@]}-1]" 

For example, if your script contains:

array=( "$@" ) unset "array[${#array[@]}-1]"    # Removes last element -- also see: help unset for i in "${array[@]}"; do   echo "$i" done 

invoking it with: bash scriptname foo bar baz produces:

foo bar 
like image 36
devnull Avatar answered Sep 23 '22 07:09

devnull