call macro twice in foreach call in Make - foreach

I have a macro that calls a target for each seed:
define MY_MACRO
$(foreach seed, $(shell $(SHELL_EXPORT) seq $(3) $(4)), $(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), FIRST_TARGET_NAME)))
endef
Is there a way I can call two different targets, one followed by the other? This one calls my FIRST_TARGET_NAME for every seed with the TEST_TARGET_MACRO.
Something like this...
define MY_MACRO
$(foreach seed, $(shell $(SHELL_EXPORT) seq $(3) $(4)), $(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), FIRST_TARGET_NAME), $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), SECOND_TARGET_NAME)))
endef
so that it will eval the first call and then the second call for each seed.
I couldn't seem to find a way to do this.... or find anything online

I'm not really sure what you're trying to do, but why can't you just write the eval/call twice? Like this:
define MY_MACRO
$(foreach seed, $(shell $(SHELL_EXPORT) seq $(3) $(4)), \
$(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), FIRST_TARGET_NAME) \
$(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), SECOND_TARGET_NAME))))
endef
Here's my simple, complete example:
TEST_TARGET_MACRO = all:: ; $(info 1=$1 2=$2 3=$3 4=$4)
define MY_MACRO
$(foreach seed, $(shell seq $(3) $(4)), \
$(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), FIRST_TARGET_NAME) \
$(eval $(call TEST_TARGET_MACRO, $(1), $(2), $(seed), SECOND_TARGET_NAME))))
endef
$(call MY_MACRO,foo,bar,2,5)
and here's the output which is just what I'd expect:
1= foo 2= bar 3= 2 4= FIRST_TARGET_NAME
1= foo 2= bar 3= 2 4= SECOND_TARGET_NAME
1= foo 2= bar 3= 3 4= FIRST_TARGET_NAME
1= foo 2= bar 3= 3 4= SECOND_TARGET_NAME
1= foo 2= bar 3= 4 4= FIRST_TARGET_NAME
1= foo 2= bar 3= 4 4= SECOND_TARGET_NAME
1= foo 2= bar 3= 5 4= FIRST_TARGET_NAME
1= foo 2= bar 3= 5 4= SECOND_TARGET_NAME
make: 'all' is up to date.

Related

Minted in beamer

This snippet
\begin{minted}{bash}
docker run --rm -p 8888:8888 \
-v %CD%/eleve:/home/jovyan/work \
-e JUPYTER_ENABLE_LAB=yes \
jupyter/scipy-notebook
\end{minted}
works fine in an article document but leads to an error in an frame environment in a beamer document.
! FancyVerb Error:
Extraneous input ` docker run --rm -p 8888:8888 \ -v -e JUPYTER_ENABLE_LAB=ye
s \ jupyter/scipy-notebook \end {minted} \end {beamer#frameslide}\ifbeamer#twos
creenstext \beamer#dosecondscreennow {{\tt lanceNotebook.bat} \begin {minted}{b
ash} docker run --rm -p 8888:8888 \ -v -e JUPYTER_ENABLE_LAB=yes \ jupyter/scip
y-notebook \end {minted} }\fi \ifbeamer#anotherslide \advance \beamer#slideinfr
ame by 1\relax \relax \expandafter \iterate \fi \let \iterate \relax \beamer#wr
iteslidentry \beamer#reseteecodes ' between \begin{minted}[<key=value>] and lin
e end
.
\FV#Error ... {FancyVerb Error:
\space \space #1
}
l.87 \end{frame}
This input will be discarded. Hit <return> to continue.
)
Runaway argument?
! File ended while scanning use of \FancyVerbGetLine.
<inserted text>
\par
<*> tuto-docker.tex
I suspect you have forgotten a `}', causing me
to read past where you wanted me to stop.
I'll try to recover; but if the error is serious,
you'd better type `E' or `X' now and fix your file.
! Emergency stop.
<*> tuto-docker.tex
*** (job aborted, no legal \end found)
Ok: just add the [containsverbatim] option to the frame environment.
Thanks to : LaTex, issue with Beamer and Listings

Output first match for each pattern

Text file to be searched (input.txt):
GREEN TREE CONIFER
GREEN BUSH BERRY
RED LEAF MAPLE
RED TRUNK MAPLE
Input pattern file; one word per line (patterns.txt):
GREEN
MAPLE
Desired output:
GREEN TREE CONIFER
RED LEAF MAPLE
My command:
$ grep -m1 -f patterns.txt input.txt
However, this only returns:
GREEN TREE CONIFER
How should I modify my command to get only the first match, from each pattern in the patterns.txt file?
I haven't come up with a single grep invokation solution.
Here I propose a loop to get first occurence for each pattern in input file.
p=$(cat pattern.txt)
for x in $(seq $(echo "$p" | wc -l)); do
cat input.txt | grep -m 1 "$(echo "$p" | head -n $x | tail -n 1)"
done

GNU parallel arguments

From the example
seq 1 100 | parallel -I ## \ > 'mkdir top-##;seq 1 100 | parallel -X mkdir top-##/sub-{}
How do -X , ##, {} work? Also, what will be the behavior when '1' or '.' is passed inside {}? Is /> used for redirection here?
I was trying to go through the tutorial from https://www.youtube.com/watch?v=P40akGWJ_gY&list=PL284C9FF2488BC6D1&index=2 and reading through man parallel page. I am able to gather some basic knowledge but not exactly how to use it or as such.
Let's do the easy stuff first.
The backslash (\) is just telling the shell that the following line is a continuation of the current one, and the greater than sign (>) is the shell prompting for the continuation line. It is no different from typing:
echo \
hi
where you will actually see this:
echo \
> hi
hi
So, I am saying you can ignore \> and just run the command on a single line.
Next, the things in {}. These are described in the GNU Parallel manual page, but essentially:
{1} refers to the first parameter
{2} refers to the second parameter, and so on
Test this with the following where the column separator is set to a space but we use the parameters in the reverse order:
echo A B | parallel --colsep ' ' echo {2} {1}
B A
{.} refers to a parameter, normally a filename, with its extension removed
Test this with:
echo fred.dat | parallel echo {.}
fred
Now let's come to the actual question, with the continuation line removed as described above and with everything on a single line:
seq 1 100 | parallel -I ## 'mkdir top-##;seq 1 100 | parallel -X mkdir top-##/sub-{}'
So, this is essentially running:
seq 1 100 | parallel -I ## 'ANOTHER COMMAND'
Ole has used ## in place of {} in this command so that the substitutions used in the second, inner, parallel command don't get confused with each other. So, where you see ## you just need to replace it with the values from first seq 1 100.
The second parallel command is pretty much the same as the first one, but here Ole has used X. If you watch the video you link to, you will see that he previously shows you how it works. It actually passes "as many parameters as possible" to a command according to the system's ARGMAX. So, if you want 10,000 directories created, instead of this:
seq 1 10000 | parallel mkdir {}
which will start 10,000 separate processes, each one running mkdir, you will start one mkdir but with 10,000 parameters:
seq 1 10000 | parallel -X mkdir
That avoids the need to create 10,000 separate processes and speeds things up.
Let's now look at the outer parallel invocation and do a dry run to see what it would do, without actually doing anything:
seq 1 100 | parallel -k --dry-run -I ## 'mkdir top-##;seq 1 100 | parallel -X mkdir top-##/sub-{}'
Output
mkdir top-1;seq 1 100 | parallel -X mkdir top-1/sub-{}
mkdir top-2;seq 1 100 | parallel -X mkdir top-2/sub-{}
mkdir top-3;seq 1 100 | parallel -X mkdir top-3/sub-{}
mkdir top-4;seq 1 100 | parallel -X mkdir top-4/sub-{}
mkdir top-5;seq 1 100 | parallel -X mkdir top-5/sub-{}
mkdir top-6;seq 1 100 | parallel -X mkdir top-6/sub-{}
mkdir top-7;seq 1 100 | parallel -X mkdir top-7/sub-{}
mkdir top-8;seq 1 100 | parallel -X mkdir top-8/sub-{}
...
...
mkdir top-99;seq 1 100 | parallel -X mkdir top-99/sub-{}
mkdir top-100;seq 1 100 | parallel -X mkdir top-100/sub-{}
So, now you can see it is going to start 100 processes, each of which will make a directory then start 100 further processes that will each create 100 subdirectories.

ImageMagick montage natural file order

I am trying to use the ImageMagick montage feature to combine chunks of maps from a game. My issue is that the game's original files are naturally ordered like
part1.png
part2.png
...
part10.png
ImageMagick reads this and will tile part10.png after part1.png. Is there a flag/option to tell IM to read the directory the way I want it to? This is a live code sample of what I'm doing.
montage \
-alpha on \
-background none \
-mode concatenate \
-tile x{$grid} \
-mattecolor none \
{$input_dir}/*.png \
{$output_file}
You can possibly use sort -g (that's general numeric sort) to get what you want.
Test:
Create 12 dummy files:
for i in {1.12} ; do touch ${i}.txt ; done
List the files:
ls -1 *.txt
1.txt
10.txt
11.txt
12.txt
2.txt
3.txt
4.txt
5.txt
6.txt
7.txt
8.txt
9.txt
Use sort -g to list them in different order:
ls -1 *.txt | sort -g
1.txt
2.txt
3.txt
4.txt
5.txt
6.txt
7.txt
8.txt
9.txt
10.txt
11.txt
12.txt
Real Life:
Now apply this to solve your problem:
montage \
-alpha on \
-background none \
-mode concatenate \
-tile x{$grid} \
-mattecolor none \
$(ls -1 {$input_dir}/*.png | sort -g) \
{$output_file}
If your $input_dir name doesn't contain any spaces, this should work flawlessly.

imagemagick comosite proportion to image size

I want to place year on picture with imagemagick. I have about 4000 pictures. I try to do it with imagemagick using the -compose parameter.
Logo is 200x67 px.
But all pictures is not the same size. How i can add proportional size of year on each image?
Example image
I not yet try imagemagick, but i placed logo to two different pictures with photoshop.
Or imagemagick handles this? Or i can put text on each image with defined font size? Or better convert all images to one size? If that, can imagemagick tell me wich is smallest picture?
I suggest you do the following:
Create the logo in a bigger size, so you can scale it down later
Then loop through all images:
Get image size of image:
$size_array = getimagesize ( $image_src );
$width = $size_array[0];
$height = $size_array[1];
Depending on image size, scale a copy of logo down
Compose logo over image
I made script http://pastebin.com/HdBMx2Zm It looks good in my XP machine (ACDSee) and also on windows 7 (windows integrated image viewer). In some pictures year is little bit bolder, but it is ok.
#!/bin/bash
#
#
#
# find /media/sf_test/meklee/ -type f -iname "*.jpg" -exec /root/imagick_script.sh "{}" \;
#
# depends on jhead and imagemagick
# if call find from another file, then is possible to count all pictures, place count on file and in imagick_script.sh
# decrase that amount by 1.
#
# in script some directory names is in Latvian :)
#
backgroundimage=$1
bgp=/media/sf_test/
if [ -f "${bgp}stop" ]
then
echo -ne "*"
exit 0
fi
if [ ! -d "${bgp}2019" ]
then
mkdir -p "${bgp}2019"
fi
# "%[fx:w] %[fx:h] %[exif:DateTime]" (use this if images has no exif data)
#dim=`identify -format "%[fx:.15*w] %[fx:.15*h] %[exif:orientation] %[exif:DateTime]" "$backgroundimage"`
# be careful with auto-orient
# see this: http://www.imagemagick.org/script/command-line-options.php?#auto-orient
#orient=`echo $dim | awk '{print $3}'`
#if [ "$orient" != "1" ]
#then
#orient image (rewrite original)
# convert -auto-orient "$1" "$1"
#re-read image data
# dim=`identify -format "%[fx:.15*w] %[fx:.15*h] %[exif:orientation] %[exif:DateTime]" "$backgroundimage"`
#fi
# jhead is much faster...
#ww=`echo $dim | awk '{print $1}'`
#hh=`echo $dim | awk '{print $2}'`
#ww=`printf "%.0f\n" "${ww}"`
#hh=`printf "%.0f\n" "${hh}"`
ww=`jhead "$1" | grep 'Resolution' | awk '{print $3}'`
hh=`jhead "$1" | grep 'Resolution' | awk '{print $5}'`
ww=`echo "$ww * .15" | bc -l | xargs printf "%1.0f"`
hh=`echo "$hh * .15" | bc -l | xargs printf "%1.0f"`
if [ "$hh" -gt "$ww" ]
then
let ww=$ww*2
fi
#year=`echo $dim | awk '{print substr($4,1,4)}'`
# works only if exif is avaiable..
year=`jhead "$1" | grep 'File date' | awk '{print substr($4,1,4)}'`
# i have images takin in range from 2004 to 2012, so if some exim data is removed, use year 2019..
case "$year" in
'2004')
#
;;
'2005')
#
;;
'2006')
#
;;
'2007')
#
;;
'2008')
#
;;
'2009')
#
;;
'2010')
#
;;
'2011')
#
;;
'2012')
#
;;
*)
year=2019
mv "$1" "${bgp}2019"
echo -ne "!"
exit 0
;;
esac
if [ ! -f ${bgp}${year}.png ];
then
convert -gravity southeast -size 300x130 xc:transparent -font Courier-bold -pointsize 125 -fill red -draw "text 0,0 '${year}'" ${bgp}output.png
composite ${bgp}output.png ${bgp}fons.png ${bgp}${year}.png
#echo "${year}.png not found, create one ..";
fi
Watermark=${bgp}${year}.png
Fname="${backgroundimage##*/}"
Fdir="${backgroundimage:0:${#backgroundimage} - ${#Fname}}"
#echo "${Fdir}new_$Fname"
#echo "${ww}x$hh $1"
if [ ! -d "/media/sf_test/resize/$year/" ]
then
mkdir "/media/sf_test/resize/$year/"
fi
if [ ! -d "/media/sf_test/apstradatie/$year/" ]
then
mkdir "/media/sf_test/apstradatie/$year/"
fi
if [ ! -f "/media/sf_test/resize/$year/$Fname" ]
then
composite -gravity southeast \( $Watermark -resize ${ww}x${hh} \) "$backgroundimage" "/media/sf_test/resize/$year/$Fname"
fi
mv "$1" "/media/sf_test/apstradatie/$year"
#"${Fdir}neew_$Fname"
echo -ne "."

Resources