Makefile problem with files beginning with "#" - makefile

I have a directory "FS2" that contains the following files:
ARGH
this
that
I have a makefile with the following contents.
Template:sh= ls ./FS2/*
#all: $(Template)
echo "Template is: $(Template)"
touch all
When I run "clearmake -C sun" and the file "all" does not exist, I get the following output:
"Template is: ./FS2/#ARGH# ./FS2/that ./FS2/this"
Modifying either "this" or "that" does not cause "all" to be regenerated. When run with "-d" for debug, the "all" target is only dependent on the directory "./FS2", not the three files in the directory. I determined that when it expands "Template", the "#" gets treated as the beginning of a comment and the rest of the line is ignored!
The problem is caused by an editor that when killed leaves around files that begin with "#". If one of those files exists, then no modifications to files in the directory causes "all" to be regenerated.
Although, I do not want to make compilation dependent on whether a temporary file has been modified or not and will remove the file from the "Template" variable, I am still curious as to how to get this to work if I did want to treat the "#ARGH#" as a filename that the rule "all" is dependent on. Is this even possible?

I have a directory "FS2" that contains the following files: #ARGH# ...
Therein lies your problem. In my opinion, it is unwise using "funny" characters in filenames. Now I know that those characters are allowed but that doesn't make them a good idea (ASCII control characters like backspace are also allowed with similar annoying results).
I don't even like spaces in filenames, preferring instead SomethingLikeThis to show independent words in a file name, but at least the tools for handling spaces in many UNIX tools is known reasonably well.
My advice would be to rename the file if it was one of yours and save yourself some angst. But, since they're temporary files left around by an editor crash, delete them before your rules start running in the makefile. You probably shouldn't be rebuilding based on an editor temporary file anyway.
Or use a more targeted template like: Template:sh= ls ./FS2/[A-Za-z0-9]* to bypass those files altogether (that's an example only, you should ensure it doesn't faslely exclude files that should be included).

'#' is a valid Makefile comment char, so the second line is ignored by the make program.
Can you filter out (with grep) the files that start with # and process them separately?

I'm not familiar with clearmake, but try replacing your template definition with
Template:sh= ls ./FS2/* | grep -v '#'
so that filenames containing # are not included in $(Template).

If clearmake follows the same rules as GNU make, then you can also re-write your target using something like Template := $(wildcard *.c) which will be a little more intelligent about files with oddball names.

If I really want the file #ARGH# to contribute to whether the target all should be rebuilt as well as be included in the artifacts produced by the rule, the Makefile should be modified so that the line
Template:sh= ls ./FS2/*
is changed to
Template=./FS2/*
Template_files:sh= ls $(Template)
This works because $(Template) will be replaced by the literal string ./FS2/* after all and in the expansion of $(Template_files).
Clearmake (and GNU make) then use ./FS2/* as a pathname containing a wildcard when evaluating the dependencies, which expands in to the filenames ./FS2/#ARGH# ./FS2/that ./FS2/this and $(Template_files) can be used in the rules where a list of filenames is needed.

Related

Running command on windows does not allow quotations

when i run a command on windows 10 command line that requires a path as one of its params, it works if the path is NOT inside a quotation, but if a path has a space in it, i need to wrap it inside quotes so that it treats as one single path, but then it complains that the file in that path does not exists.
For example:
C:/PROJECTS/desktopfiles/public/libs/cpdf/win64/cpdf.exe C:/Users/john/Documents/cat.pdf C:/Users/john/Documents/my_dog.pdf -o C:/Users/john/Documents/cat_dog_Merged.pdf
The above works,
the below doesn't (because there is a space in my dog.pdf)
C:/PROJECTS/desktopfiles/public/libs/cpdf/win64/cpdf.exe C:/Users/john/Documents/cat.pdf C:/Users/john/Documents/my dog.pdf -o C:/Users/john/Documents/cat_dog_Merged.pdf
You could try to replace spaces with a question mark. The question mark is a wildcard to match "any single character", which would be a space in your case. Like this: my?dog.pdf. Just make sure that there is no other file matching this pattern. But the system should give you some error message then (which might or might not point to the root of the problem).
Another solution that comes to my mind is a batch file that renames the files in question automatically (replacing spaces with underscores) and renames them back after the pdf merge.

How can I debug .gitignore file handling?

I’m having lots of trouble convincing git to ignore files in my project.
Basically, sometimes it works, sometimes it just seems to ignore the .gitignore file for no obvious reason. (By “seems” I mean that there are patterns in it that look as if they should exclude something, but that something is not excluded.)
There’s a 'git check-ignore' command, but it only says which pattern matched a file. But I can’t find any option to make it say which patterns it’s found and where, nor why those patterns do not match a file.
Is there a way to do this kind of debugging?
P.S. There is a single issue which I did find, and I’m mentioning it here in case it helps others:
I was adding patterns using “echo pattern >> .gitignore”, which at least on my system results in spaces at the of the line (i.e., everything between “echo” and “>>” is echoed in the file, except for the first space character after “echo”).
Git does not trim those spaces when matching patterns, so for the command above it wouldn’t match a file named “pattern” but it would match “pattern{space}”.
I think most of my issues stem from this. Those extra spaces are hard to notice, so I’d still like a debug command that makes sure I notice them, if there is one.
Edit #1:
Yes, I did try -v. For example:
> mkdir test
> touch test/file.txt
> echo test >> .gitignore
> git check-ignore -v test/file.txt
(nothing is printed)
> echo test>> .gitignore
> git check-ignore -v test/cuc.txt
.gitignore:8:test test/cuc.txt
Note the extra space in the first echo line, which makes it enter “test[space]” as a pattern. As I mentioned, “check-ignore” tells you what matched, but it doesn’t tell you what didn’t nor why.

Testing "framework" for scripts with nonstandard filenames

Here are many comments on some questions (especially for shell) that say basically one or more of the following:
This will fail on file names that contain spaces, newlines, etc,
This will fail if the file is a symbolic link (or not),
This will fail if the $filaneme is a directory and not regular file,
and so on.
While I understand that every script needs its own testing environment, but
these are some common things for what the script should be immune against.
So, my intention is to write a script what will create some directory hierarchy
with "specially crafted" file names for testing purposes.
The question is: what "special" file names are good for this test?
Currently I have (the script creates files and directories) with:
space in the file name
newline in the file name
file name that starts with one of:
- (like command argument)
# (comment char)
! (command history)
file name that contains one of:
| char (pipe)
() chars
* and ? (wildcards)
file name with unicode characters
all above for the directories
symbolic link to the directory
symbolic link to the file
Any other idea what I shouldn't miss?
What comes to my mind:
quotes in the filename single and double
the $ character at the start
several redirection characters like > < << <<<
the ~ char ($HOME)
the ';' (as command delimiter)
backslash in the filename \
basically, go thru ascii table and test all chars, if you think that you need this :)
Some another comments:
If you want test scripts for the stack-overflow questions, you should create one file with the OP's content (calling as the "basic file")
And the all above "special files" should be symlinks to the above basic file. With this method you can easily modify the content of the files (you need change only one - the basic).
Or, if symlinks not a solution for you use hard-links.
Not directly about special characters in the filenames, but it is good care about:
different case filenames, especially for images like image.jpg image.JPG, same filename only different extension
EDIT: Ideas from the comments:
Very long filenames, lots and lots of files, and very deep directory hierarchies (tripleee)

why doesn't *.abc match a file named .abc?

I thought I understood wildcards, till this happened to me. Essentially, I'm looking for a wild card pattern that would return all files that are not named .gitignore. I came up with this, which seems to work for all cases I could conjure:
ls *[!{gitignore}]
To really validate if this works, I thought I'd negate the expression and see if it returns the file named .gitignore (actually any file that ended with gitignore; so 1.gitignore should also be returned). To that effect, I thought the negated expression would be:
ls *[{gitignore}]
However, this expression doesn't return a files named .gitignore (although it returns a file named 1.gitignore).
Essentially, my question, after simplification, boils down to:
Why doesn't *.abc match a file that is named .abc
I think I can take it from there.
PS:
I am working on Mac OSX Lion (10.7.4)
I wanted to add a clause to .gitignore such that I would ignore every file, except .gitignore in a given folder. So I ended up adding * in the .gitignore file. Result was, git ended up ignoring .gitignore :)
From the numerous searches I've made on google - Use the asterisk character (*) to represent zero or more characters.
I assume you're using Bash. From the Bash manual:
When a pattern is used for filename expansion, the character ‘.’ at the start of a filename or immediately following a slash must be matched explicitly, unless the shell option dotglob is set.
.gitignore patterns, however, are treated differently:
Otherwise, git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not match a / in the pathname.
According to the fnmatch(3) docs, a leading dot has to be explicitly matched only if the FNM_PERIOD flag is set, so *gitignore as a gitignore pattern would match .gitignore.
There is an easier way to accomplish this, though. To have .gitignore ignore everything except .gitignore:
*
!.gitignore
If you want to ignore everything except the gitignore file, use this as the file:
*
!.gitignore
Lines starting with an exclamation point are interpreted as exceptions.

Linux shell list file what's the difference bewteen tmp/**/* and tmp/*

I encounter one problem about the file system in the shell.
what's difference between tmp/**/* and tmp/*?
I make the experiment in my system,
have this directory dir2
dir2
-->dir1
-->xx2
-->ff.txt
and I run ls dir2/*:
dir2/ff.txt
dir2/dir1:
xx2
then I run ls dir2/**/*:
dir2/dir1/xx2
So it means the ** is to ignore this directory(like ignore the dir1),
Can some one help me ?
I think there's a formatting issue in the question test, but I'll answer based on the question title and examples.
There shouldn't be any difference between a single and double asterisk at any single level of the path. Either expression matches any name, except for hidden ones which start with a dot (this can be changed by shell options). So:
tmp/**/* (equivalent to tmp/*/*) is expanded to all names which are nested two levels deep in tmp. The first asterisk expands only to directories and not files at the first level because it's followed by a slash.
tmp/* expands to anything nested one level deep inside tmp.
To this comes the fact that ls will list contents of directory if a directory is given on its command line. This can be overridden by adding -d option to ls.

Resources