What does ${1-1} in bash mean? - bash

I'm reading the scripts from here and trying to understand what's going on. This function performs changing the directory of a Finder window:
function ee {
osascript -e 'set cwd to do shell script "pwd"'\
-e 'tell application "Finder"'\
-e "if (${1-1} <= (count Finder windows)) then"\
-e "set the target of window ${1-1} to (POSIX file cwd) as string"\
-e 'else' -e "open (POSIX file cwd) as string"\
-e 'end if' -e 'end tell';\
};\
I'm assuming the $ is interpreted by bash, since it's inside double-quotes. I haven't been able to find what could {1-1} mean. I've played with the expression in separate test scripts but couldn't find a difference from plain $1. Any ideas?

This means that if argument 1 (${1}) is not set, it will be set to 1.
See parameter substitution here.
${parameter-default}, ${parameter:-default}
If parameter not set, use default.

Related

Multiple Applescript lines from terminal osascript call

So I'm trying to run multiple Applescript commands from the command line in one go. However, no matter how I try it, it won't work:
$ osascript -e "set x to 0; display dialog x"
$ osascript -e "set x to 0 \n display dialog x"
$ osascript -e "set x to 0 then display dialog x"
Is there a way to do this without saving to file?
This works for me:
osascript -e "set x to 0" -e "display dialog x"
Have a look at the -e option in the manual page for osascript in Terminal: man osascript
−e statement
Enter one line of a script. If −e is given, osascript will not look for a filename in the argument list. Multiple −e options may be given to build up a multi-line script. Because most scripts use char- acters that are special to many shell programs (for example, AppleScript uses single and double quote marks, “(”, “)”, and “∗”), the statement will have to be correctly quoted and escaped to get it past the shell intact.
You can also do e.g.:
osascript <<END
set x to 0
display dialog x
END
Or:
osascript -e '
set x to 0
display dialog x'
Your second attempt was very close to proper:
osascript -e "set x to 0
PRESS ENTER
display dialog x"
PRESS ENTER

Proper formatting of Command Substitution

I am trying to add the currently playing song if there is one to my ZSH prompt. I'm using a JXA command osascript -l JavaScript -e "Application('Music').currentTrack.name()". I am trying to assign it to a variable. and then echo that command.
precmd() {
SONG=$( echo -e osascript -l JavaScript -e "Application('Music').currentTrack.name()" )
LEFT=echo $SONG
RIGHT="$(dracula_time_segment) $(battery_pct_prompt)"
RIGHTWIDTH=$(($COLUMNS-${#LEFT}))
}
I've tried a number of variations eg: echo inside and outside the expression and various flags.
You don't need echo at all, as demonstrated by your later command substitutions when setting RIGHT; command substitution just takes a command and executes it.
SONG=$(osascript -l JavaScript -e "Application('Music').currentTrack.name()")
LEFT="$SONG"
You could combine the previous two commands; SONG isn't needed.
LEFT=$(osascript ...)

Escaping many layers of cascaded single and double quotes in osx bash

I use a Mac (osx sierra) and I have been learning how to use the bash. I am trying new stuff as I go along to grasp some concepts. This time I was experimenting with functions and aliases. But then I couldn't wrap my head around this problem:
I first echoed this function into the .profile to insert new aliases and functions easily into the .profile file.
function editprofile(){
echo "$#" >> ~/.profile
}
This function worked very well for some alias insertions. But after I tried to insert an alias for the script (the script below) that makes my mac sleep, I realized that the function creates some diffuculties with the cascading single and double quotes. I believe this will be the case for most scripts that uses lots of layers of single and double quotes.
osascript -e 'tell application "Finder" to sleep' && exit
The code below is me trying to use my function to insert the code above as an alias into the .profile.
editprofile 'alias _sleep=' "'" 'osascript -e' "'" 'tell application "Finder" to sleep' "'" '&& exit' "'"
The problem is that when the second script is echoed into the .profile file, I should still keep some escape characters, otherwise the code is interpretted by the bash incorrectly. I think this would also be the case with may other scripts that have this many layers of quotes, so I though I should ask if there is any way around.
P.S.
On a related note, it seems like when I type this:
function editprofile(){echo "$#" >> ~/.profile}
instead of this:
function editprofile(){
echo "$#" >> ~/.profile
}
into the .profile file, the script doesn't work. Is it because of the line breaks?
Assuming that you have a function, as opposed to an alias:
_sleep() { osascript -e 'tell application "Finder" to sleep' && exit; }
...you can emit its text with declare -f. Thus:
declare -f _sleep >>~/.profile
...or, to use your existing editprofile function:
editprofile "$(declare -f _sleep)"
The easiest approach is just that: Define the function in your local shell, then have the shell itself do the work of emitting it -- and quote that emitted content so it doesn't get field-split into individual arguments (and then have those arguments individually evaluated as globs).
If you don't want to go that route, there are approaches available; they're just varying degrees of unpleasant.
printf -v cmd_var '%q ' osascript -e 'tell application "Finder" to sleep'
...will put correctly-quoted contents into "$cmd_var". You could then:
printf -v sleep_def '_sleep() { %s && exit; }' "$cmd_var"
...which will give you a function declaration in sleep_dev that can be evaled to execute it locally, or appended to your .profile, &c.
editprofile "$sleep_def"
...will behave appropriately in that context.

osascript using bash variable with a space

I am using osascript in Bash to display a message in Notification Center (Mac OS X) via Apple Script. I am trying to pass a text variable from Bash to the script. For a variable without spaces, this works just fine, but not for one with spaces:
Defining
var1="Hello"
var2="Hello World"
and using
osascript -e 'display notification "'$var1'"'
works, but using
osascript -e 'display notification "'$var2'"'
yields
syntax error: Expected string but found end of script.
What do I need to change (I am new to this)? Thanks!
You could try to use instead :
osascript -e "display notification \"$var2\""
Or :
osascript -e 'display notification "'"$var2"'"'
This fixes the problem of manipulation of variables that contains spaces in bash. However, this solution doesn't protect against injections of osascript code. So it would be better to choose one of Charles Duffy's solutions or to use bash parameter expansion :
# if you prefer escape the doubles quotes
osascript -e "display notification \"${var2//\"/\\\"}\""
# or
osascript -e 'display notification "'"${var2//\"/\\\"}"'"'
# if you prefer to remove the doubles quotes
osascript -e "display notification \"${var2//\"/}\""
# or
osascript -e 'display notification "'"${var2//\"/}"'"'
Thank to mklement0 for this very useful suggestion !
This version is completely safe against injection attacks, unlike variants trying to use string concatenation.
osascript \
-e "on run(argv)" \
-e "return display notification item 1 of argv" \
-e "end" \
-- "$var2"
...or, if one preferred to pass code in on stdin rather than argv:
osascript -- - "$var2" <<'EOF'
on run(argv)
return display notification item 1 of argv
end
EOF

Convert AppleScript to one line

I'm using Mach Desktop to echo a script's results into a Desklet, so it has to be in this format:
echo 'tell application "iTunes" to return album of current track' | osascript
I have a single line in which to enter data, so the script needs to be one long string.
It may be that the entire thing must be contained within one set of single quotes after echo, as follows:
echo '[entire script]' | osascript
How do I convert the AppleScript below to one line?
set some_file to "Macintosh HD:Users:Zade:Library:Application Support:Notational Data:Words.txt" as alias
set the_text to read some_file as string
set the text item delimiters of AppleScript to ", "
set the_lines to (every text item of the_text)
return some item of the_lines
Here is what I'm trying:
echo 'set some_file to "Macintosh HD:Users:Zade:Library:Application Support:Notational Data:Words.txt" as alias -e set the_text to read some_file as string -e set the text item delimiters of AppleScript to ", " -e set the_lines to (every text item of the_text) -e return some item of the_lines' | osascript
And that gives this error:
107:112: syntax error: A "set" can't go after this identifier. (-2740)
I suppose you could try out this script. I'm confused as to what you're actually trying to accomplish, though, so I apologize if this script is unsatisfactory.
echo 'set some_file to "~/Library/Application Support/Notational Data/Words.txt" as POSIX file as alias' -e 'set the_text to read some_file' -e 'set the text item delimeters of AppleScript to ","' -e 'set the lines to (every text item of the_text)' -e 'return the lines' | osascript
EDIT: #Zade That would be because Words.txt doesn't exist. Aliases only refer to existing files. Therefore, you must choose a file that exists. Here is an easy way to see what the correct syntax is for file references:
set some_file to (choose file)
You will notice that the file path is delimited by colons ( : ) rather than slashes. Having said this, choose a file that exists, and run your script with that file.

Resources