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.
You can also get all but the last argument with
which, honestly, is a little sketchy, since it seems to be (ab)using the fact that arguments are numbered starting with 1, not 0.
Update: This only works due to a bug (fixed in 4.1.2 at the latest) in handling
$@
. It works in version 3.2.Assuming that you already have an
array
, you can say:For example, if your script contains:
invoking it by saying:
bash scriptname foo bar baz
would return:I have used this
bash
one-liner beforeIt 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 extractscount
characters fromvariable
starting at position. In the special case wherevariable
is@
, which means the argument list, it extractscount
arguments from the list beginning atposition
. Here,position
is1
for the first argument andcount
is one less than the number of arguments worked out previously.set -- arg1...argn
sets the argument list to the given argumentsSo 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.