Cannot copy files of directory into other directory - makefile

I have a Makefile which should copy all dot files for me into the home directory. Unfortunately GNUMake does not support wildcards as used in bash and the common wildcards $(wildcard *.c) are limited to special file types.
My Makefile is:
SHELL := /bin/bash
profile:
#cp -r profile/ $(HOME)/
.PHONY: profile
Other variations I tried so far:
cp -r profile/* $(HOME) => cp: cannot stat profile/*: No such file or directory
cp -r profile/$(wildcard *) $(HOME) => tries to copies all files in the current directory
cp -r $(wildcard profile/*) $(HOME)/ => cp: missing destination file operand after /home/foobar
cp -r $(wildcard profile/*) $(HOME)/$(wildcard profile/*) =>cp: missing destination file operand after /home/foobar`

Try The shell Function using direct shell commands in makefile
profile:
$shell(cp -r profile/* $(HOME)/)
.PHONY: profile
Otherwise set HOME variable at the beggining like this
SHELL := /bin/bash
HOME := $(shell echo $HOME)
profile:
#cp -r profile/* $(HOME)/
.PHONY: profile

Related

simple loop over files in some directory makefile

I can easily print all the files inside some directory from bash:
$ cat go.sh
BASEDIR=~/Downloads
MYDIR=${BASEDIR}/ddd
for f in $(ls ${MYDIR}); do echo $f; done
$ ./go.sh
m.txt
d.txt
When I try to do a similar thing from makefile it doesn't work well:
$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
for f in $(ls ${MYDIR}); do echo ${f}; done
$ make
for f in ; do echo ; done
And here is another trial that doesn't work:
$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
for f in $(shell ls ${MYDIR}); do echo ${f}; done
$ make
for f in d.txt m.txt; do echo ; done
Maybe you can do it purely Makefile way?
MYDIR = .
list: $(MYDIR)/*
#echo $^
You can still run command from Makefile like this
MYDIR = .
list: $(MYDIR)/*
for file in $^ ; do \
echo "Hello" $${file} ; \
done
If I were you, I'd rather not mix Makefile and bash loops based on $(shell ...). I'd rather pass dir name to some script and run loop there - inside script.
Also almost "true way" from documentation
TEMPLATES_DIR = ./somedir
list:
$(foreach file, $(wildcard $(TEMPLATES_DIR)/*), echo $(file);)
Here is the edited answer based on #Oo.oO:
$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
#for f in $(shell ls ${MYDIR}); do echo $${f}; done
$ make
d.txt
m.txt
There is a little problem with #Oo.oO's answer.
If there is any file/folder has the same name with a target in makefile, and that target has some prerequisites, and you want to loop through that folder, you will get that target recipe being executed.
For example: if you have a folder named build, and you have a rule like:
build: clean server client
clean:
#echo project cleaned!
server:
#echo server built!
client:
#echo client built!
To loop through the folder contains that special build folder, let's says you have the following rules:
MYDIR = .
ls: $(MYDIR)/*
#echo $^
The result will be:
$ make ls
project cleaned!
server built!
client built!
build Makefile
I would suggest to use #Mike Pylypyshyn's solution. According to the make documentation, the foreach function is more suitable in this case.

Odd cp behavior in bash script

I have a bash script that is copying some files, but it doesn't seem to be working properly. A side note is that there are no matching files in the source directory. But the point of the script is to copy files if there are files to copy.
A basic snippet of what I'm trying to do:
source_loc=/u01
target_log=/u02
/usr/bin/cp "$source_loc"/dir/*file* "$target_loc"/dir/
Results in
Usage: cp [-fhipHILPU][-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src target
or: cp [-fhipHILPU] [-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src1 ... srcN directory
If I add set -x to my script, I get this...
+ /usr/bin/cp /u02/dir/
Usage: cp [-fhipHILPU][-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src target
or: cp [-fhipHILPU] [-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src1 ... srcN directory
+ set +x
The EXTRA peculiar thing about this is that if I re-run the script without changing anything, I get this as my output:
cp: /u01/dir/*file*: No such file or directory
Now I haven't tested this script with matching files in the source (I will be very shortly) but I want to make sure I'm not missing something. I don't care about getting an error, I just want to be sure I get the correct error (i.e. no such file or directory).
Any insight would be appreciated.
You can use find as suggested by #elliotfrisch:
find "$source_dir/dir" -type f -name "*file*" -maxdepth 1 -exec cp {} "$target_loc/dir" \;
Alternatively, in Bash, you can capture the glob results into an array and invoke cp when the array is not empty:
shop -s nullglob # glob expands to nothing if there are no matching files
files=("$source_loc/dir/"*file*)
((${#files[#]} > 0)) && cp "${files[#]}" "$target_loc"/dir/

Tar: Cannot stat: No such file or directory even though directory exists

I've created a temporary directory in a Makefile:
export TMP := $(shell mktemp -d -t), do a bunch of work there. Then I want to create a tarball.
tar czf ../packages/$(PACKAGE).lin.tar.gz -C $(TMP) $(PACKAGE).lin
The issue is that this command always gives
Tar: Cannot stat: No such file or directory
I've added a test to see if the directory exists using this right before the tar:
if [ -d $(TMP)/$(PACKAGE).lin ]; then echo "Dir exists"; fi
I see the echo, the directory does exist. I also cannot cd into that directory!?
Also, it seems to be dropping the latter part of the directory name...it will say cannot stat'$(PACKAGE)' instead of '$(PACKAGE).lin'.
If I do this:
cd $(TMP)
tar czf ../packages/$(PACKAGE).lin.tar.gz $(PACKAGE).lin
Then it will say cannot stat $(PACKAGE).lin.

copy multiple files with certain prefixs

How do i copy files with with the certain prefixs e.g. LTE*.html, Voicemail*.html
$ ls
2G_3G_cccccc.html other_dddd.html other3_dddd.html Voicemail_bbbbbb.html
LTE_aaaa.html other2_dddd.html subdir1
I have tried this but no joy
$ cp '(LTE*|Voice*).html' subdir1/
cp: cannot stat `(LTE*|Voice*).html': No such file or directory
So this would be the result I want
$ ls subdir1/
Voicemail_bbbbbb.html LTE_aaaa.html
Use brace expansion
cp {LTE,Voice}*.html subdir1/
Which expands to
cp LTE*.html Voice*.html subdir1/

Read a file permission and apply to another in shell

I am writing a script and I want to apply the permissions of a given file to another, given that the owner of both files is the same. The files can be huge, so moving the file contents using
cp dest tmp
rm dest
cp source dest
echo tmp > dest
rm tmp
is not an option.
Does your chmod support the --reference option? It does exactly what you need.
FILE1="$HOME/.bashrc"
FILE2="$HOME/.profile"
FPERM=`stat -c "%a" "$FILE1"`
chmod $FPERM "$FILE2"
PS. If also ownership:
FUID=`stat -c "%U" "$FILE1"`
FGID=`stat -c "%G" "$FILE1"`
chown $FUID:$FGID "$FILE2"

Resources