How to manipulate string in GNUmakefile for loop - gnu-make

I am new to GNUmakefile and I am just not sure how to handle the strings in the for loop below. I can print out each file using the echo command below. My questions are:
1. How to assign the $$f to a variable?
2. How to print out the content of the new variable?
For example, I did assign the content of $$f to "abc" but echo ${abc}; prints out blank.
Where did I miss? Thanks
DIR := MyDir
CFILES := $(wildcard $(DIR:=/*.c))
.PHONY: all
all:
for f in $(CFILES); \
echo $$f; \
abc=$$f; \
echo ${abc}; \
done

Your for loop is missing a do?
Inside the tabbed block you have scripting.
So you are setting shell vars not make vars.
You must escape the $s in shell block so printing $$abc or $${abc} would work. You can use make var as you have done $(CFILES).
What do you expect/want in abc ?
Do you wish to manipulate a shell or make var?
echo CFILES=$(CFILES)
for f in $(CFILES); do\
echo ff $$f;\
abc=$$f; \
echo $${abc};\
bn=$$(basename $$f);\
b=$${bn%%.*};\
echo you want this b= stripped down file tag $$b basename of file $$bn bash style;\
done
As ever there are more than one ways of doing things.
Make style maybe you could use pattern rules and automatic vars to do what you want?
http://www.gnu.org/software/make/manual/make.html#Automatic-Variables
http://www.gnu.org/software/make/manual/make.html#Pattern-Examples
e.g.
%.o : %.c
echo make var $< matches file.c
echo make var $# matches file.o
echo make var $* matches stem file
echo $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#

Related

script to watch new files in a folder and when found, based on filename call different scripts

I am trying to design a file watcher solution in which I need to watch a particular folder for different file names everyday, once the file name is found, I need to call a script specific to the file name.
Example:
Watch Folder -
file1.txt
file2.txt
file3.txt
call script.sh abc file1
call script.sh abc file2
call script.sh abc file3
I tried to make use of the inotifywait but have not been able to get it to work. Any help would be appreciated.
sftp_home=/app/public/ent_sftp
script=/app/public/bin
curr_date=$(TZ=":US/Eastern" date '+%Y%m%d')
inotifywait -m $sftp_home -e create -e moved_to |
while read path action file; do
echo "The file '$file' appeared in directory '$path' via '$action'"
if [ "$file" = "file1${curr_date}*.txt" ]; then
echo "file1${curr_date}*.txt was found and process will be initiated"
cd $script
./script.sh file1
elif [ "$file" = "file2${curr_date}*.txt" ]; then
echo "file2${curr_date}*.txtwas found today and process will be initiated"
cd $script
./script.sh file2
fi
done
Thanks,
Kavin
If you want to do glob expansions in the match, you can do that with a case statement:
unset arg
case $file in
file1${curr_date}*.txt)
arg=file1
;;
file2${curr_date}*.txt)
arg=file2
;;
*)
echo No file found >&2
;;
esac
if test -n "$arg"; then
echo "${arg}${curr_date}*.txt was found and process will be initiated"
cd $script
./script.sh "$arg"
fi

How to get everything after an extension unix

I have a file name like
filename.txt.zip_20180202_30291_233
In script variable i will have filename in a variable and extension in variable
like
echo $fileprefix
filename
echo $filesuffix
.txt.zip
How do i rename the file to below one ? Moving everything after extension to before extension ? (Note: there could be any numbers after extension )
filename_20180202_30291_233.txt.zip
#!/bin/sh
prefix='filename'
suffix='.txt.zip'
name='filename.txt.zip_20180202_30291_233'
newname="$prefix${name#$prefix$suffix}$suffix"
echo mv "$name" "$newname"
This would output
mv filename.txt.zip_20180202_30291_233 filename_20180202_30291_233.txt.zip
The parameter substitution ${name#$prefix$suffix} removes $prefix$suffix, i.e. filename.txt.zip, from the start of $name, which gives you _20180202_30291_233. This is then prepended with $prefix and appended with $suffix to create $newname.
Looping over all files that matches "$prefix$suffix"* in the current directory and renaming all:
for name in "$prefix$suffix"*; do
newname="$prefix${name#$prefix$suffix}$suffix"
echo mv "$name" "$newname"
done
The echo is there for protection. Remove it once you are certain the code will do the right thing.
file_orig=filename.txt.zip_20180202_30291_233
fileprefix=filename
filesuffix=.txt.zip
file="${file_orig#$fileprefix}"
file="${file#$filesuffix}"
file="$fileprefix$file$filesuffix"
echo "$file"
filename_20180202_30291_233.txt.zip
https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion

Run arbitrary zsh command for all subfolders

I'm currently using this function to run a command for all subfolders in zsh.
forsubdirs() {
for dir in *; do
(cd ${dir} && echo $fg_bold[yellow]${PWD##*/}$reset_color && $# && echo '\n')
done
}
I use it like this: forsubdirs git pull
The problem, though: it does not work with aliases. How to execute an arbitrary ZSH command (including aliases and lists of commands separated with "&" or ";") for all subfolders?
In order to be able to pass complex commands as argument you need to quote syntactic elements like ; and &. The arguments then need to be explicitly evaluated with the eval command. For example:
forsubdirs () {
for dir in *(/) ; do
( cd $dir && echo $fg_bold[yellow]${PWD##*/}$reset_color && eval $# && echo '\n' )
done
}
forsubdir 'ls -1 | sed "s/^/ /"'
Also, I would suggest using *(/) instead of plain *. It matches only directories, so that the function does not even try to run cd on regular files.

sub string in unix on a character

I have file names inside a directory in unix as:
code1_abc.txt
code2_xyz.txt
code1_pqr.txt
I am looping over all files in this director to do some stuff on each files:
for myFile in $(ls $INPUT_DIR/* | xargs -n 1 basename)
do
echo $myFile
done
However, now I want to split the file name and want to get the part before the underscore i.e. code1, code2, code3
for myFile in $(ls $INPUT_DIR/* | xargs -n 1 basename)
do
echo $myFile
codeForCurrentFile= // want code1 here using myFile value
echo $codeForCurrentFile // should echo code1, code2, code3 respectively
done
How to do this? I am using korn shell.
Thanks for reading!
Use ksh pattern substitution to replace the underscore and anything after it with nothing (effectively delete):
echo ${myFile//_*/}
For your example:
codeForCurrentFile=${myFile//_*/}
More info here (see section 4.5.4): http://docstore.mik.ua/orelly/unix3/korn/ch04_05.htm
You can do this by calling out to an external program, regardless of the shell in use (provided it supports output capture of external programs, of course), such as with the following transcript:
pax$ fspec=code1_abc
pax$ echo $fspec
code1_abc
pax$ pre=`echo $fspec | cut -d_ -f1` ; echo $pre
code1
pax$ post=`echo $fspec | cut -d_ -f2` ; echo $post
abc
There are a wide variety of tools you can use to achieve this, cut (as above, probably the simplest), awk, sed and so on.
This has the disadvantage of kicking up external processes, something that should be okay provided you're not doing it many times per second. If it's something that needs to be fast, you're better off using shell-specific internal methods, such as:
ksh:
fspec=code1_abc
pre=${fspec//_*/}
post=${fspec//*_/}
bash:
fspec=code1_abc
pre=${fspec%%_*}
post=${fspec#*_}
csh:
set fspec = code1_abc
set arr = ( $fspec:as/_/ / )
set pre = $arr[1]
set post = $arr[2]

How to quote strings in file names in zsh (passing back to other scripts)

I have a script that has a string in a file name like so:
filename_with_spaces="a file with spaces"
echo test > "$filename_with_spaces"
test_expect_success "test1: filename with spaces" "
run cat \"$filename_with_spaces\"
run grep test \"$filename_with_spaces\"
"
test_expect_success is defined as:
test_expect_success () {
echo "expecting success: $1"
eval "$2"
}
and run is defined as:
#!/bin/zsh
# make nice filename removing special characters, replace space with _
filename=`echo $# | tr ' ' _ | tr -cd 'a-zA-Z0-9_.'`.run
echo "#!/bin/zsh" > $filename
print "$#" >> $filename
chmod +x $filename
./$filename
But when I run the toplevel script test_expect_success... I get cat_a_file_with_spaces.run with:
#!/bin/zsh
cat a file with spaces
The problem is the quotes around a file with spaces in cat_a_file_with_spaces.run is missing. How do you get Z shell to keep the correct quoting?
Thanks
Try
run cat ${(q)filename_with_spaces}
. It is what (q) modifier was written for. Same for run script:
echo -E ${(q)#} >> $filename
. And it is not bash, you don't need to put quotes around variables: unless you specify some option (don't remember which exactly)
command $var
always passes exactly one argument to command no matter what is in $var. To ensure that some zsh option will not alter the behavior, put
emulate -L zsh
at the top of every script.
Note that initial variant (run cat \"$filename_with_spaces\") is not a correct quoting: filename may contain any character except NULL and / used for separating directories. ${(q)} takes care about it.
Update: I would have written test_expect_success function in the following fashion:
function test_expect_success()
{
emulate -L zsh
echo "Expecting success: $1" ; shift
$#
}
Usage:
test_expect_success "Message" run cat $filename_with_spaces

Resources