recursive user defined function in makefile runs out of stack memory - recursion

I have a function that returns all the files in a directory.
# Returns all files in folder recursively that match pattern
#
# $(call rwildcard, folder,pattern)
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
Argument 1, i.e. folder, is the path of the folder where to search for files recursively and it's user provided
If this argument is "/" this would run out of memory and crash with an exception.
Is there a way to prevent this? besides filtering "/" as an argument.
Note: i'm using cygwin

I suspect you aren't making any progress in the inner rwildcard. If it matches "." every time, are you stuck in a loop?
Can you use another tool to get a list of files?
r := $(shell find $(dir) -type f -name \*$(likethis)\*)

Related

Passing wildcards to find

I'm trying to automate my test runner better. For that I need the update file name in a variable. As this name depends on a the version I'm trying to use a find with a pattern to get the file name. That works just fine in bash.
However if I use that same pattern in expect find complains that it can't find anything.
My guess is that expect is doing something to my wildcards. However my experiments with {}, "", '' or \ didn't result in it working.
I guess I could create a helper sh script to write it into a file and then read that file but I don't like that solution and there has to be an option to pass characters with special tcl meaning as arguments.
At the moment my call looks something like this with an absolute path in front of the pattern:
set pattern {[0-9]*/*test*}
set updateFile [exec find ${pattern} -type f]
The result is that find reports '[0-9]*/*test*': No such file or directory. The pattern is what I would expect and when I call find [0-9]*/*test* -type f in bash it results in the expected file path. Find also works fine as long as I don't have any wild cards.
Has anybody an idea what is wrong?
When you run find [0-9]*/*test* -type f in Bash, it's Bash who interprets the wildcard [0-9]*/*test* and expand it to multiple files. And then Bash would pass the expanded multiple files to find. That's to say find never sees the wildcard.
For exec find $pattern -type f, Tcl would not interpret what's in $pattern and pass it directly to find. Unfortunately find also does not interpret the wildcards here so it fails with error like find : '[0-9]*/*test*': No such file or directory.
To work around, you can invoke find with bash -c:
exec bash -c "find $pattern -type f"

Zsh filename expansion over multiple directories recursively

Problem: I have a directory $BASE, and in this directory (and/or any of the directories below it) are zero or more directory entries matching the pattern *.x. I want to loop over all these entries. I want to use foreach and not find $BASE -name '*.x' for this procedure. I have zsh 5.3.
My current approach goes like this:
foreach f in $BASE/*.x(N) $BASE/**/*.x(N)
do
# ... do something with $f
done
Is there a way to write the glob pattern more uniformely (not requiring the repetition of *.x)?
foreach f in $BASE/**/*.x(N) is sufficient. ** already matches 0 or more directories, so the pattern matches $BASE/*.x already.

GNU Makefile, use a variable containing the dependent directories

I am trying to create a Makefile
I have a Makefile variable containing dependent directories like
DEPDIR := temp foo bar
I need the absolute path of each directory. So, I wrote a rule:
DIRS := $(foreach dirs, $(DEPDIR), $(shell find $(HOME) -name "$$dirs"))
and I also tried:
DIRS := $(notdir $(foreach dirs, $(DEPDIR), $(shell find $(HOME) -name "$$dirs")))
But variable DIRS in both case is empty.
Am I missing something here?
Using find for this is completely wacky. There may be directories elsewhere in the directory tree with the same name, and anyway, presumably, the ones you want are in the current directory.
If they can be nested within other directories, running find on the current directory might make some sense, but you are probably simply looking for
$(patsubst %,${PWD}/%,$(DIRS))
I've no idea why did you write double $: $$dirs. Try this:
DIRS := $(foreach dir, $(DEPDIR), $(shell find $(HOME) -type d -name "$(dir)" ))
Consider narrowing down the search criteria, since $(HOME) by definition can contain anything.
I guess you will not argue that it'd be better to keep track of the project dependencies using a dedicated directory. And there are many ways to build such kind of directories(generating symlinks, downloading/extracting compressed packages, cloning repositories, using package managers etc.). Therefore, I'll suggest the following pattern as well.
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))
DIRS := $(realpath $(addprefix $(PROJECT_DIR)deps/, dir1 dir2 dir3))
Here we extract filename of the current makefile from MAKEFILE_LIST, then store its absolute path in MAKEFILE_PATH variable. Then the directory part of the path to the makefile is stored in PROJECT_DIR. By means of addprefix we prepend $(PROJECT_DIR)/deps to the front of each dependent directory(dir1 dir2 dir3). Then we resolve symlinks, and construct canonical absolute names for the dependent directories, then store them in DIRS.

Use of find in unix on strange file/directory names [duplicate]

Im a beginner scripter, writing scripts in tcsh and csh(these are teached in my course)
Im writing a script which uses find for putting path of directories
this is the part of the script:
set list = (`find $PATH -type d`)
it works fine until the file or directory names arent named such as:
#fi##lename&& or −filename or :−,?!drectoryanem!-``
These special characters i couldnt handle i changed the find script to:
set list = ("`find $PATH -type d`")
bit none of these works, when i want to use the path from the list in this next script:
foreach i ($list:q)
foreach file (`find "$i" -maxdepth 1 -type f`)
....
end
end
it couldnt handle these special file names, so i get many errors like find: −."!filename: no such filename or directory
I worked it out
It had to be this way:
set subor = ("`find "'"$i"'" -type f -maxdepth 1`")
now it ignores everything in the filenames
and in:
foreach j ($subor:q)
i quoted it this way it ignores the white characters in file names

UNIX C Shell Scripting. Copying files and adding extension

I'm trying to write a script that copies files from one directory to another and adds a .bak extension to them. I'm having a hard time figuring out how to add the extension.
foreach file in ($argv[1]/*)
cp $file $argv[2]
end
Making a bunch of assumptions (mainly that the outline of your script is valid C shell syntax, and that spaces in file names are not an issue), then you probably need to use the basename command:
foreach file in ($argv[1]/*)
cp $file $argv[2]/`basename $file`.bak
end
The basename command removes the pathname, so the files will be copied precisely to the directory named by $argv[2]. If you're looking to retain directory hierarchies too, you have to work a fair bit harder.
$1 and $2 are the arguments (directories) to the script-:
for f in $1/*
do
fname=$(basename $f)
cp $f $2/$fname.bak
done

Resources