Filenames and Pathnames in Shell: How to Do It Correctly (2010)
dwheeler.com
dwheeler.com
In the case of the first example he shows, the cat -n problem, you can do the following in zsh to expand the results of the wildcard globbing automatically:
cat *(:A)
This will give cat full paths. Not significantly different from the PWD referenced with ./* in his example, but more universal in applicability, particularly when you start to use things like the file type filters: cat *(.:A)
giving you only files, not directories, and also expanding to absolute paths, while cat **/*(.:A)
does the same for plain files in the working directory and all subdirectories as well.Remember to test your patterns with a print statement first:
print -l **/*(.:A)
before passing them to a command.ZSH has an option to expand globs onto the command line the first time you hit return, and issue the command the second. I don't remember what it is.
However if you have more than a handful of matches it's going to be a suboptimal method of eyeballing the glob results.
I prefer to use `print -l` as it will break the glob results on separate lines.
An additional benefit of ZSH is that it will normally return each glob result as an independent item (this avoids the problem bash has with just returning strings that in turn are broken on IFS characters). Using that flag with print will give you a clear sense of the actual results.
With human-manageable strings comes ambiguities, especially in concatenative situations like commandline expansion and SQL injection susceptible code.
There's really no good universal solution. Judiciously adding explicit boilerplate as the article describes, or using less open-ended syntax which ends up adding common syntactic overhead as well, are both more painful to the user in common cases.
How you replace syntax-based structuring is the hard part, but it's not impossible.
At the interface level, nested navigable fields.
>Even data structures in memory have a (binary) syntax
No, they don't. Syntax is the expression of structure through the arrangement of the contents of a single sequence. Data structures as they are typically realized express structure through the relationships between several sequences.
Can someone explain the following:
for file in ./* ; do # Prefix with "./*", NEVER begin with bare "*"
if [ -e "$file" ] ; then # Make sure it isn't an empty match
1. Why prefix with a "./" ? Is that just to help avoid the `cat $filename` scenario? (i.e., that $filename will be "./-n" instead of "-n", and that cat -- *
is perfectly valid?)2. What's the -e check for? It says "an empty match" — -e means that the file exists, but * would only return files that exist, so -e must (with some caveats) be true. (The caveat being that there's a race condition between the globbing and the test, but with the added test, there's _still_ a race condition between the glob, the test, and the command execution. Are we just attempting to minimize the amount of race-condition by testing?)
2. I think this is for the situation where the glob doesn't match, and the nullglob shell option is not set. Without that option, a non-matching glob is processed as a regular word. e.g. In an empty directory:
$ for file in ./*; do echo $file; done
./*
Note the glob pattern is printed by the echo statement. The -e test catches this condition.[1] on my BSD system, many internal Tcl commands honor this convention. Damned if I can find a section 1 shell command that uses the convention, but I'm sure I've seen them.
[2] my version of cat doesn't have a -- flag, so my example is contrived; not sure if GNU cat differs.
EDIT: typo, perl(1) supports "--". See perlrun(1) for details.
import shutilThis alleviates the problems described in the article.
cat * > ../collection # works is PS
cat $file # works even if $file contains unusual characters. If $file is an *array* it "cats" multiple paths. If wildcards are not expected cat -lit $file should be used (literal path).dir /s
Since / can not be in filename, so it avoids the problem compeletely.
So, it turns out that when Windows wanted to launch things, it would find the first exe it could, then apply the rest of the command as args. "c:\program" comes before "c:\program files\", so every time a user went to launch a program, windows would find the "c:\program" exe first, and apply the rest of the string as args (" files/and/rest/of/string"). So the launcher would fire up, and it ignored the args. For some reason I can't recall, Windows kept looking for the right program and eventually it would launch as well.
So the end-user, on trying to run any application, would get that application plus the game's launcher, all because of the crazy way Windows searches it's path... well, when combined with a crazy virus checker behaviour.
Unfortunately I can't recall the checker or the game, sorry.
http://www.commonexploits.com/unquoted-service-paths/
There's even a hint of privilege escalation there (but not always: writing to C:\ still requires root in most cases).