Show and execute - foreach

In this makefile
dirs = $(shell ls)
clean:
$(foreach dir,$(dirs),echo $(dir);)
The output is
$ make clean
echo bin; echo install.sh; echo Makefile; echo README.md; echo utils;
bin
install.sh
Makefile
README.md
utils
Why does it first show the command, then execute it?
How I can omit the first line?

Prepend the command with the # character. Example:
dirs = $(shell ls)
clean:
#$(foreach dir,$(dirs),echo $(dir);)

From the manual (5.2 Recipe Echoing, bold emphasis mine):
Normally make prints each line of the recipe before it is executed. We call this echoing because it gives the appearance that you are typing the lines yourself.
When a line starts with #, the echoing of that line is suppressed. The # is discarded before the line is passed to the shell. [...]
Alternatively:
The -s or --silent flag to make prevents all echoing, as if all recipes started with #.

Related

extraneous end if in .dep.inc file

I am giving a job to Jenkins to build binaries for my code through make file . It is showing error of extraneous end if in .dep.inc file,I tried to change the configuration of net beans.
This file is getting generated from auto generated make file in net beans. In net beans it is compiling but in Jenkins it is showing error.*
# dependency checking support
.depcheck-impl:
#echo "# This code depends on make tool being used" >.dep.inc
#if [ -n "${MAKE_VERSION}" ]; then \
echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
echo "include \$${DEPFILES}" >>.dep.inc; \
echo "endif" >>.dep.inc; \
else \
echo ".KEEP_STATE:" >>.dep.inc; \
echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
fi
you are using BASH syntax instead of Makefile. One option could be to use the conditional structure of Makefile:
Conditional Parts of Makefiles
Another way is to define the whole BASH instruction in the same line, like that:
if [ <condition>]; then <action1>; else <action2>; fi
In Makefile, each line of a target could be a SHELL, but you should not split them.
Finally, you can use the "define" environment to insert BASH code:
define <name>=
<BASH code>
<...>
<name>: ; #$(value <name>)
.ONESHELL
I hope you find it useful!

ROS how to find all executables of a package?

I want to ask how to find all the executable names of a package in ROS (Robot Operating System)? For example, find spawn_model in gazebo_ros package. When I inspect the package in my system, it just shows some .xml, .cmake files, without any executables. But I can run it, such as: rosrun gazebo_ros spawn_model.
Thank you!
An easy way to do this is to type: "rosrun name_of_package " and then press tab two times, it should show you all the executables built.
After looking in the bash autocompletion script for rosrun, it looks like the command catkin_find is used to find the location of the executables for a package, and the executables are filtered with a find command.
If you want to create a script to give you a list of the executables follow the instructions below:
Save the following script in a file called rospack-list-executables:
#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "usage: $(basename $0) <pkg_name>"
echo ""
echo " To get a list of all package names use the command"
echo " 'rospack list-names'"
exit
fi
pkgname=${1}
pkgdir="$(catkin_find --first-only --without-underlays --libexec ${pkgname})"
if [[ -n "${pkgdir}" ]]; then
find -L "${pkgdir}" -executable -type f ! -regex ".*/[.].*" ! -regex ".*${pkgdir}\/build\/.*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g" | sort
else
echo "Cannot find executables for package '${pkgname}'." >&2
exit 1
fi
Then make the rospack-list-executables script executable (chmod +x rospack-list-executables) and place it in a directory that can be found in your $PATH environment variable.
Run the script:
$ rospack-list-executables gazebo_ros
debug
gazebo
gdbrun
gzclient
gzserver
libcommon.sh
perf
spawn_model
You should get the same result that you get when you type the rosrun <pkgname> command and press Tab:
$ rosrun gazebo_ros
debug gazebo gdbrun gzclient gzserver libcommon.sh perf spawn_model
You can check the executables for all packages with the following bash code:
rospack list-names | while read pkgname; do
echo "Executables for package '${pkgname}':";
rospack-list-executables $pkgname; echo "";
done
To enable package autocompletion for your newly created command, type the following:
complete -F _roscomplete rospack-list-executables
If you do not want to have to type the complete command every time you login, you can append it to your .bashrc file:
echo "complete -F _roscomplete rospack-list-executables" >> ~/.bashrc
Now when you type the command rospack-list-executables and press the Tab key, you should get a list of all the available packages to choose from.
catkin_find --first-only --without-underlays --libexec <your package name>)
should give you the folder where the executables are

Is there a good macvim git diff?

I have been using textmate for many years and I just made the switch to macvim and one thing that I used all the time with textmate was the command git df which in my .gitconfig was just an alias for
[alias]
df = !git diff | mate
and what that did was give me a screen like this
Is there a replacement in mvim that I can add somewhere for me to get similar behavior
I describe what I use here.
Basically, add the following lines to your "~/.gitconfig":
[diff]
tool = default-difftool
[difftool "default-difftool"]
cmd = default-difftool.sh $LOCAL $REMOTE
With the following wrapper script:
#! /bin/bash
if [[ -f /Applications/MacVim.app/Contents/MacOS/Vim ]]
then
# bypass mvim for speed
VIMPATH='/Applications/MacVim.app/Contents/MacOS/Vim -g -dO -f'
elif [[ -f /usr/local/bin/mvim ]]
then
# fall back to mvim
VIMPATH='mvim -d -f'
else
# fall back to original vim
VIMPATH='vimdiff'
fi
$VIMPATH $#
You can get the diff one file at a time by doing:
git difftool -t vimdiff
vimdiff can be replaced with gvimdiff for gvim, so I would assume you can also replace it with mvimdiff for macvim.
I am not sure of a way to pipe the entirety of git diff into vim though.

How can I tell from a within a shell script if the shell that invoked it is an interactive shell?

I'm trying to set up a shell script that will start a screen session (or rejoin an existing one) only if it is invoked from an interactive shell. The solution I have seen is to check if $- contains the letter "i":
#!/bin/sh -e
echo "Testing interactivity..."
echo 'Current value of $- = '"$-"
if [ `echo \$- | grep -qs i` ]; then
echo interactive;
else
echo noninteractive;
fi
However, this fails, because the script is run by a new noninteractive shell, invoked as a result of the #!/bin/sh at the top. If I source the script instead of running it, it works as desired, but that's an ugly hack. I'd rather have it work when I run it.
So how can I test for interactivity within a script?
Give this a try and see if it does what you're looking for:
#!/bin/sh
if [ $_ != $0 ]
then
echo interactive;
else
echo noninteractive;
fi
The underscore ($_) expands to the absolute pathname used to invoke the script. The zero ($0) expands to the name of the script. If they're different then the script was invoked from an interactive shell. In Bash, subsequent expansion of $_ gives the expanded argument to the previous command (it might be a good idea to save the value of $_ in another variable in order to preserve it).
From man bash:
0 Expands to the name of the shell or shell script. This is set
at shell initialization. If bash is invoked with a file of com‐
mands, $0 is set to the name of that file. If bash is started
with the -c option, then $0 is set to the first argument after
the string to be executed, if one is present. Otherwise, it is
set to the file name used to invoke bash, as given by argument
zero.
_ At shell startup, set to the absolute pathname used to invoke
the shell or shell script being executed as passed in the envi‐
ronment or argument list. Subsequently, expands to the last
argument to the previous command, after expansion. Also set to
the full pathname used to invoke each command executed and
placed in the environment exported to that command. When check‐
ing mail, this parameter holds the name of the mail file cur‐
rently being checked.
$_ may not work in every POSIX compatible sh, although it probably works in must.
$PS1 will only be set if the shell is interactive. So this should work:
if [ -z "$PS1" ]; then
echo noninteractive
else
echo interactive
fi
try tty
if tty 2>&1 |grep not ; then echo "Not a tty"; else echo "a tty"; fi
man tty :
The tty utility writes the name of the terminal attached to standard
input to standard output. The name that is written is the string
returned by ttyname(3). If the standard input is not a terminal, the
message ``not a tty'' is written.
You could try using something like...
if [[ -t 0 ]]
then
echo "Interactive...say something!"
read line
echo $line
else
echo "Not Interactive"
fi
The "-t" switch in the test field checks if the file descriptor given matches a terminal (you could also do this to stop the program if the output was going to be printed to a terminal, for example). Here it checks if the standard in of the program matches a terminal.
Simple answer: don't run those commands inside ` ` or [ ].
There is no need for either of those constructs here.
Obviously I can't be sure what you expected
[ `echo \$- | grep -qs i` ]
to be testing, but I don't think it's testing what you think it's testing.
That code will do the following:
Run echo \$- | grep -qs i inside a subshell (due to the ` `).
Capture the subshell's standard output.
Replace the original ` ` expression with a string containing that output.
Pass that string as an argument to the [ command or built-in (depending on your shell).
Produce a successful return code from [ only if that string was nonempty (assuming the string didn't look like an option to [).
Some possible problems:
The -qs options to grep should cause it to produce no output, so I'd expect [ to be testing an empty string regardless of what $- looks like.
It's also possible that the backslash is escaping the dollar sign and causing a literal 'dollar minus' (rather than the contents of a variable) to be sent to grep.
On the other hand, if you removed the [ and backticks and instead said
if echo "$-" | grep -qs i ; then
then:
your current shell would expand "$-" with the value you want to test,
echo ... | would send that to grep on its standard input,
grep would return a successful return code when that input contained the letter i,
grep would print no output, due to the -qs flags, and
the if statement would use grep's return code to decide which branch to take.
Also:
no backticks would replace any commands with the output produced when they were run, and
no [ command would try to replace the return code of grep with some return code that it had tried to reconstruct by itself from the output produced by grep.
For more on how to use the if command, see this section of the excellent BashGuide.
If you want to test the value of $- without forking an external process (e.g. grep) then you can use the following technique:
if [ "${-%i*}" != "$-" ]
then
echo Interactive shell
else
echo Not an interactive shell
fi
This deletes any match for i* from the value of $- then checks to see if this made any difference.
(The ${parameter/from/to} construct (e.g. [ "${-//[!i]/}" = "i" ] is true iff interactive) can be used in Bash scripts but is not present in Dash, which is /bin/sh on Debian and Ubuntu systems.)

How can I find the location of the tcsh shell script I'm executing?

Say I put an executable tcsh file in /path/to/my_script.csh
and my current directory is anywhere, for example I'm in /path
So I type to/my_script.csh
I want to have a line in my_script.csh that will return "/path/to/my_script.csh" - like ruby's
__FILE__
In c shell, try like this:
set rootdir = `dirname $0`
set abs_rootdir = `cd $rootdir && pwd`
echo $abs_rootdir
If you want to ensure the same result (full path and script name) try something like this:
...
rootdir=`/bin/dirname $0` # may be relative path
rootdir=`cd $rootdir && pwd` # ensure absolute path
zero=$rootdir/`/bin/basename $0`
echo $zero
...
Then you can call it as foo.sh, ./foo.sh, some/lower/dir/foo.sh and still get the same result no matter how it is called.
If you want an absolute path then this should help you out:
#!/bin/tcsh -f
set called=($_)
if ( "$called" != "" ) then ### called by source
echo "branch 1"
set script_fn=`readlink -f $called[2]`
else ### called by direct execution of the script
echo "branch 2"
set script_fn=`readlink -f $0`
endif
echo "A:$0"
echo "B:$called"
set script_dir=`dirname $script_fn`
echo "script file name=$script_fn"
echo "script dir=$script_dir"
Source: http://tipsarea.com/2013/04/11/how-to-get-the-script-path-name-in-cshtcsh/
#!/bin/tcsh
echo "I am $0."

Resources