Is there a way to read shell options in Deno? For example, to detect whether the current shell is in interactive mode, I would normally check to see if $- has an i in it:
if [[ $- == *i* ]]; then
echo "interactive"
else
echo "not interactive"
fi
I can of course use Deno.run to execute ['bash', '-c', 'echo $-'], but is there any more elegant way to get access to this information?
EDIT: Actually running a bash command to print out the shell options doesn't appear to work for me either. The subprocess always reports itself as non-interactive.
You can use Deno.isatty to make this determination. Example:
const isInteractive = Deno.isatty(Deno.stdin.rid);
console.log(`${isInteractive ? '' : 'not '}interactive`);
Related
Need to check for distribution of a file in an array programmatically. Logging into a master server and then would like to check for file on workers using simple ssh. So far I have:
ssh $HOSTNAME "[ -e '$HOSTNAME:/directory/filename' ] && echo 'Exists'"
Based on some of the logging output, I know the ssh is successful, but how can I get the test to return a message to the master server? Running the above returns nothing.
SSH will exit with the same exit code as the command that you run on the remote host. If that command is a test, then the exit code will match what you would normally expect from a test.
I would suggest the following:
Simplify your command to only run the test over SSH
Run the echo on your local machine
It doesn't seem correct that you have $HOSTNAME: in front of your path.
ssh "$HOSTNAME" "test -e '/directory/filename'" && echo 'Exists'
I personally find if statements to be much more easily understandable, which is an optional change if you are willing to go that route:
if ssh "$HOSTNAME" "test -e '/directory/filename'"; then
echo "Exists"
else
echo "Does not exist" >&2
exit 1
fi
So I'm not exactly sure whether this is something wrong with optparse-applicative's script or if I'm using it wrong.
In the optparse-applicative readme, it states that programs are made available with automatic completion scripts, with options for zsh. For my program setup:
$> setup --zsh-completion-script `which setup`
Outputs:
#compdef setup
local request
local completions
local word
local index=$((CURRENT - 1))
request=(--bash-completion-enriched --bash-completion-index $index)
for arg in ${words[#]}; do
request=(${request[#]} --bash-completion-word $arg)
done
IFS=$'\n' completions=($( /Users/anrothan/.local/bin/setup "${request[#]}" ))
for word in $completions; do
local -a parts
# Split the line at a tab if there is one.
IFS=$'\t' parts=($( echo $word ))
if [[ -n $parts[2] ]]; then
if [[ $word[1] == "-" ]]; then
local desc=("$parts[1] ($parts[2])")
compadd -d desc -- $parts[1]
else
local desc=($(print -f "%-019s -- %s" $parts[1] $parts[2]))
compadd -l -d desc -- $parts[1]
fi
else
compadd -f -- $word
fi
done
I'm running the following in my zshrc (I use oh-my-zsh, but I removed it and this still happens in a bare-minimum config with only a small PATH addition to get the setup script).
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source <(setup --zsh-completion-script `which setup`)
I get the following error several times:
/dev/fd/11:compadd:24: can only be called from completion function
I've run compinit, and the completion script seems to look right to me, and I've looked around but I can't seem to figure out why this error is happening...
You don't need to source zsh-completion scripts, they just need to be added to your fpath parameter.
So just place the output of setup --zsh-completion-script $(which setup) in a file call _setup in $HOME/.config/zsh/completions.
fpath=($HOME/.config/zsh/completions $fpath)
autoload -U compinit && compinit
I was hoping I could distinguish between when a script is run interactively versus by 'at' or 'cron'. If the user is running a script on the command line I want to put output to their screen, but if it's running via 'at' or 'cron' then the output would go to a log file.
I searched online and saw many suggestions (although not AIX specific) on using the "$-". That sounded promising, but when I tried it, it wasn't as useful.
If I type 'echo "$-"' at the prompt I get "ims" back. If I create a script with the echo command, it returns "h". If I submit the script via "at" I get "h", and if I have cron run it I get "h".
I also looked at using TERM and PS1, but again they don't allow me to distinguish between a script run by either 'cron' or 'at' versus a script invoked at the command line.
Is there something else I could try on AIX?
Thanks.
If I run this script
Glenn. Here's a script I'm running. I get the desired result using "tty -s" but not with "$-". Am I doing something wrong? You see the "$-" results always says I'm not in an interactive shell.
#!/bin/ksh93
echo "tty -s"
if tty -s
then
echo " - I'm an interactive shell"
else
echo " - I'm not interactive"
fi
echo "\$-"
case $- in
*i*) echo " - I'm an interactive shell";;
*) echo " - I'm not interactive";;
esac
I get these three results sets when the script is run via 1) the command line, 2) "at", and 3) cron.
command line result
tty -s
- I'm an interactive shell
$-
- I'm not interactive
at result
tty -s
- I'm not interactive
$-
- I'm not interactive
Cron result
tty -s
- I'm not interactive
$-
- I'm not interactive
By running at the command line I mean I'm running "script.ksh >> script.log". If I run "echo $-" from the command line it returns 'ims' but when $- is reference within a script it always returns 'h'.
If the user is running a script on the command line I want to put output to their screen, but if it's running via 'at' or 'cron' then the output would go to a log file.
That's what standard output and redirection is good for. Also you can use command tty -s to determine if your standard input is a terminal or not. (If you wish to check your standard output instead: tty -s <&1)
Example (~projects/tmp/tty_test.sh):
#!/bin/sh
exec >>~projects/tmp/tty_test.log 2>&1
tty
if tty -s; then echo terminal
else echo otherwise
fi
You want to check if $- contains the letter i. If it does, you have an interactive shell:
case $- in
*i*) echo "I'm an interactive shell";;
*) echo "I'm not interactive";;
esac
Testing
$ ksh
$ case $- in
> *i*) echo "I'm an interactive shell";;
> *) echo "I'm not interactive";;
> esac
I'm an interactive shell
$ ksh <<'END'
> case $- in
> *i*) echo "I'm an interactive shell";;
> *) echo "I'm not interactive";;
> esac
> END
I'm not interactive
Given the comments below, you probably want to use this builtin test:
if [ -t 0 ]; then
: # script running interactively
else
# running non-interactively (cron or at)
# redirect output to a log file
exec 1>/path/to/logfile 2>&1
fi
# and now, your script can just output to stdout/stderr
# and the output will go to the screen or to the logfile
echo "hello"
date
print -u2 "bye"
I've got a script on my computer named test.py. What I've been doing so far to run the program is type python test.py into the terminal.
Is there a command on Unix operating systems that doesn't require the user to specify the program he/she uses to run the script but that will instead run the script using whichever program the shebang line is pointing to?
For example, I'm looking for a command that would let me type some_command test.txtinto the terminal, and if the first line of test.txt is #!/usr/bin/python, the script would be interpreted as a python script, but if the first line is #!/path/to/javascript/interpreter, the the script would be interpreted as javascript.
This is the default behavior of the terminal (or just executing a file in general) all you have to do is make the script executable with
chmod u+x test.txt
Then (assuming text.txt is in your current directory) every time you type
./text.txt
It will look at the sh-bang line and use the program there to run text.txt.
If you really want to duplicate built-in functionality, try this.
#!/bin/sh
x=$1
shift
p=$(sed -n 's/^#!//p;q' "$x" | grep .) && exec $p "$#"
exec "$x" "$#"
echo "$0: $x: No can do" >&2
Maybe call it start to remind you of the similarly useful Windows command.
I'm attempting to port over some functionality from my old .bashrc into my .zshrc and I'm having trouble with a condition that worked in bash.
Whenever I remote log in to my computer, I had bash check the $- variable to see if it was interactive. If it was, I would start up an emacs server if one wasn't already running and change to my code directory. Otherwise (if I was getting a file with scp, for example), I wouldn't do anything.
Here's the bit of code:
if [[ $- -regex-match "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
And here's the error zsh gives me: .zshrc:125: unrecognized condition:$-'`
Does anyone know how to get around this error when using $- ? I've tried quoting it, wrapping it in $(echo $-) but none have worked. Thanks in advance.
Edit: If I switch my code to:
if [[ $- =~ "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
I now get: .zshrc:125: condition expected: =~ I'm not sure exactly what zsh is interpreting incorrectly here as I'm not very familiar with the semantics of zsh's shell scripts. Could someone point me in the right direction on how to express this condition in zsh?
In zsh, you don't need to bother with $-, which is--I think--intended primarily for POSIX compatibility.
if [[ -o INTERACTIVE ]]; then
if ps -u myusername | grep -q emacs; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
-regex-match is only available if tho module zsh/regex (man 1 zshmodules) is loaded. (The error message depends on the version: I get zsh: unknown condition: -regex-match if it is not loaded on 4.3.17, but zsh:1: unknown condition: -$- on 4.3.10).
You can try [[ $- =~ "i" ]] which is not dependend on additional modules.