Retrieve output from a shell call to python in a makefile: is there a missing step? - gnu-make

I have the following makefiles:
# bash version
SHELL:=/usr/bin/env bash
H:=$(shell pwd)
install:
#echo "$H::make.$#: not implemented!"
And a python3 version:
SHELL:=/usr/bin/env python3
H:=$(shell "import os,sys; print(os.getcwd(),file=sys.stdout)")
install:
#print("$H::make.$#: not implemented!")
The bash version works perfectly, whereas the python3 version works, persay. However, the path variable $H is empty.
A check of the python expression in the shell call confirms it is working python code:
python3 -c "import os,sys; print(os.getcwd(),file=sys.stdout)"
//works
How does one comply with the expected behavior in that shell call so that make picks up the output?

That is not what the shell command you wrote actually does.
This:
SHELL:=/usr/bin/env bash
H:=$(shell pwd)
causes the equivalent of:
/usr/bin/env bash -c 'pwd'
to be run.
So, this:
SHELL:=/usr/bin/env python3
H:=$(shell "import os,sys; print(os.getcwd(),file=sys.stdout)")
causes the equivalent of this to be run:
/usr/bin/env python3 -c '"import os,sys; print(os.getcwd(),file=sys.stdout)"'
to be run. A string in Python is just a no-op statement, so this does nothing.
Remove the quotes:
H := $(shell import os,sys; print(os.getcwd(),file=sys.stdout))

Related

Why my zsh completion is not sourcing it?

I try to setup my zsh-completions. I also use oh-my-zsh .
A lot of shell commands provide a some_command completion zsh
and they often suggest sourcing it directly in .zshrc like so:
source <(kubeone completion zsh)
source <(tilt completion zsh)
source <(civo completion zsh)
I can't get it working. Only when I output the command into a file echo "$(kubeone completion zsh)" > ~/.dotfiles/completions/_kubeone.
(That ~/.dotfiles/completions/-path is in my fpath):
fpath=(/usr/local/share/zsh-completions $fpath)
fpath=(~/.dotfiles/completions $fpath)
But that approach is not that neat. I wanna make the use of adding
source $(my_command completion zsh) to my .zsh_rc file.
Interestingly SOME commands are working with that approach: like: source <(kompose completion zsh) but source <(kubeone completion zsh) wont???
Here is an excerpt from my ~/.zshrc:
#!/bin/sh
[ -f ~/.dotfiles/fubectl.source ] && source ~/.dotfiles/fubectl.source
export ZSH_THEME="powerlevel10k/powerlevel10k"
export DOTFILES=$HOME/.dotfiles
export ZSH=$DOTFILES/oh-my-zsh
BUNDLED_COMMANDS=(rubocop)
UNBUNDLED_COMMANDS=(berks foreman mailcatcher rails ruby spin rubocop)
plugins=(zsh-completions zsh-autosuggestions docker fzf bundler brew cask capistrano codeclimate coffee dotenv gem git github grunt helm heroku history iterm2 minikube node redis-cli redis-cli rails rake rake-fast ruby rbenv textmate macos pod zeus terraform)
source $ZSH/oh-my-zsh.sh
complete -o nospace -C /usr/local/bin/terraform terraform
# load autocomplete
fpath=(/usr/local/share/zsh-completions $fpath)
fpath=(~/.dotfiles/completions $fpath)
autoload -U compinit && compinit
source <(kompose completion zsh) # WORKS
source <(kubeone completion zsh) # DONT WORK
(kompose a→tab WORKS)
kubeone a→tab returns only my folder structure
❯ kubeone completion zsh
Application\ Support/ MAMP/ VirtualBox\ VMs/ oh-my-zsh
Applications/ Movies/ Wine\ Files/ output.json
Coding/ Music/ builds/
...
..
.
but should return:
❯ kubeone apply
apply -- Reconcile the cluster
completion -- Generates completion scripts for bash and zsh
config -- Commands for working with the KubeOneCluster configuration manifests
document -- Generates documentation
help -- Help about any command
install -- Install Kubernetes
...
..
.
What I tried so far:
after opening terminal rm ~/.zcompdump*, then tried command, then reopened terminal and tried command again.
autoload -Uz compinit && compinit -i with different arguments
I think there is some misconfiguration or maybe a brew formula is disturbing?
Here is the complete output of my brew list command, as well my complete .zshrc file: https://gist.github.com/exocode/79c9acfad9828b73d05d2abfa39f1724

UNIX commands from R via shell function

I need to issue unix commands from an R session. I'm on Windows R2 2012 server using RStudio 1.1.383 and R 3.4.3.
The shell() function looks to be the right one for me but when I specify the path to my bash shell (from Git for Windows install) the command fails with error code 127.
shell_path <- "C:\\Program Files\\Git\\git-bash.exe"
shell("ls -a", shell = shell_path)
## running command 'C:\Program Files\Git\git-bash.exe /c ls -a' had status 127'ls -a' execution failed with error code 127
Pretty sure my shell path is correct:
What am I doing wrong?
EDIT: for clarity I would like to pass any number of UNIX commands, I am just using ls -a for an example.
EDIT:
After some playing about 2018-03-09:
shell(cmd = "ls -a", shell = '"C:/Program Files/Git/bin/bash.exe"', intern = TRUE, flag = "-c")
The correct location of my bash.exe was at .../bin/bash.exe. This uses shell with intern = TRUE to return the output as an R object. Note the use of single quote marks around the shell path.
EDIT: 2018-03-09 21:40:46 UT
In RStudio we can also call bash using knitr and setting chunk options:
library(knitr)
```{bash my_bash_chunk, engine.path="C:\\Program Files\\Git\\bin\\bash.exe"}
# Using a call to unix shell
ls -a
```
Two things stand out here. Bash will return exit code 127 if a command is not found; you should try running the fully qualified command name.
I also see that your shell is being run with a /c flag. According to the documentation, the flag argument specifies "the switch to run a command under the shell" and it defaults to /c, but "if the shell is bash or tcsh or sh the default is changed to '-c'." Obviously this isn't happening for git-bash.exe.
Try these changes out:
shell_path <- "C:\\Program Files\\Git\\git-bash.exe"
shell("/bin/ls -a", shell = shell_path, flag = "-c")
Not on Windows, so can't be sure this will work.
Perhaps you need to use shQuote?
shell( paste("ls -a ", shQuote( shell_path) ) )
(Untested. I'm not on Windows. But do read ?shQuote))
If you just want to do ls -a, you can use the below commands:
shell("'ls -a'", shell="C:\\Git\\bin\\sh.exe")
#or
shell('C:\\Git\\bin\\sh.exe -c "ls -a"')
Let us know if the space in "Program Files" is causing problems.
And if you require login before you can call your command,
shell('C:\\Git\\bin\\sh.exe --login -c "ls -a"')
But if you are looking at performing git commands from R, the git2r by ropensci might suit your needs.

Clozure CL compiled executable losing certain command line arguments

I'm writing a utility program in Common Lisp and building it with Clozure CL; I would like to be able to use the command-line option -d with the program, but for some reason this particular option won't make it through to (ccl::command-line-arguments). Here is a minimal example:
(defun main ()
(format t "~s~%" (ccl::command-line-arguments))
(quit))
I compiled with
(save-application "opts"
:toplevel-function 'main
:prepend-kernel t)
and here's some sample output:
~/dev/scratch$ ./opts -c -a -e
("./opts" "-c" "-a" "-e")
~/dev/scratch$ ./opts -c -d -e
("./opts" "-c" "-e")
~/dev/scratch$ ./opts -b --frogs -c -d -e -f -g -h --eye --jay -k -l
("./opts" "--frogs" "-c" "-e" "-f" "-g" "-h" "--eye" "--jay" "-k" "-l")
The -b and -d options appear to be getting lost. The documentation on command line arguments for ccl isn't very helpful. I thought maybe because ccl itself takes -b as an argument, that option might have gotten eaten for some reason, but it doesn't take -d (which is eaten), and it does take -e and -l which aren't. Nothing on saving applications seemed helpful.
I'm pretty sure it's Clozure-specific (and not, say, the shell eating them), because other stuff seems to be getting all the arguments:
#!/usr/bin/python
import sys
print sys.argv
yields
~/dev/scratch$ ./opts.py -a -b -c -d -e
['./opts.py', '-a', '-b', '-c', '-d', '-e']
and
#!/bin/bash
echo "$#"
gives
~/dev/scratch$ ./opts.sh -a -b -c -d -e
-a -b -c -d -e
This is all taking place on lubuntu 15.10 with bash as the shell.
If anyone could shed some light on why this is happening or how I can end up with all my command-line switches, I'd be appreciative.
Thanks.
According to the source code of the 1.11 release, -b and -d are options used by the lisp kernel.
Since I'm unsure about licence issues, I just provide the link to the relevant file: http://svn.clozure.com/publicsvn/openmcl/release/1.11/source/lisp-kernel/pmcl-kernel.c
Command line arguments are processed in the function process_options, where for options -b (--batch) and -d (--debug) - among others - a variable num_elide is set to 1. A bit further down, this leads to overwriting the option with the following argument (argv[k] = argv[j];).
The code also shows a possible fix: Supply -- (two dashes) once as argument before -b or -d. When above function encounters a -- it stops processing the rest of the arguments, thus leaving them unchanged to be possibly taken up into "lisp world" shortly after.
Turns out this has already been solved at SO before:
https://stackoverflow.com/a/5522169/1116364

run zsh script in specified folder

How to run zsh script in specified folder? How to specify a folder to run a script:
zsh script_name.sh
Documents said that: "-s Force shell to read commands from the standard input. If the -s flag is not present and an argument is given, the first argument is taken to be the pathname of a script to execute." but it does not work.
What is the difference between zsh -c ~/path1/ script1.sh (2 parameters) and zsh -c ~/path1/script1.sh?
You should just open a subshell, Execute the following from zsh or bash (including the parentheses):
(cd ~/path1 && source script1.sh)
Note: If your script is written for zsh, name it script1.zsh instead, since zsh syntax is not retro-compatible with old sh's.
This should work:
zsh -c "cd ~/path1 && ./script_name.sh"

Whats the difference between running a shell script as ./script.sh and sh script.sh

I have a script that looks like this
#!/bin/bash
function something() {
echo "hello world!!"
}
something | tee logfile
I have set the execute permission on this file and when I try running the file like this
$./script.sh
it runs perfectly fine, but when I run it on the command line like this
$sh script.sh
It throws up an error. Why does this happen and what are the ways in which I can fix this.
Running it as ./script.sh will make the kernel read the first line (the shebang), and then invoke bash to interpret the script. Running it as sh script.sh uses whatever shell your system defaults sh to (on Ubuntu this is Dash, which is sh-compatible, but doesn't support some of the extra features of Bash).
You can fix it by invoking it as bash script.sh, or if it's your machine you can change /bin/sh to be bash and not whatever it is currently (usually just by symlinking it - rm /bin/sh && ln -s /bin/bash /bin/sh). Or you can just use ./script.sh instead if that's already working ;)
If your shell is indeed dash and you want to modify the script to be compatible, https://wiki.ubuntu.com/DashAsBinSh has a helpful guide to the differences. In your sample it looks like you'd just have to remove the function keyword.
if your script is at your present working directory and you issue ./script.sh, the kernel will read the shebang (first line) and execute the shell interpreter that is defined. you can also call your script.sh by specifying the path of the interpreter eg
/bin/bash myscript.sh
/bin/sh myscript.sh
/bin/ksh myscript.sh etc
By the way, you can also put your shebang like this (if you don't want to specify full path)
#!/usr/bin/env sh
sh script.sh forces the script to be executed within the sh - shell.
while simply starting it from command line uses the shell-environemnt you're in.
Please post the error message for further answers.
Random though on what the error may be:
path specified in first line /bin/bash is wrong -- maybe bash is not installed?

Resources