Is this really what we want? $ ls -1 no_such_file ls: cannot access 'no_such_file': No such file or directory $ ls -1 no_such_file 2> /dev/null $ ls -1 no_such_file(N) aaa aa-messagefunctions aliases aliases,1,remove _find_match aliases,2,STARTCOM ... .... lists the whole directory. It's not exactly what one might expect. I can see that if the argument 'disappears' entirely then 'ls' thinks 'ls *' but shouldn't 'ls' be in a 'not found' condition rather than a 'list all' condition?
On Fri, Jan 29, 2021 at 4:24 PM Ray Andrews <rayandrews@eastlink.ca> wrote:
>
> Is this really what we want?
>
> $ ls -1 no_such_file
> ls: cannot access 'no_such_file': No such file or directory
>
> $ ls -1 no_such_file 2> /dev/null
>
> $ ls -1 no_such_file(N)
> aaa
> aa-messagefunctions
> aliases
> aliases,1,remove _find_match
> aliases,2,STARTCOM
> ...
>
> .... lists the whole directory. It's not exactly what one might
> expect. I can see that if the argument 'disappears' entirely then
> 'ls' thinks 'ls *' but shouldn't 'ls' be in a 'not found' condition
> rather than a 'list all' condition?
`ls` without arguments lists files in the current directory. This is
mandated by POSIX and what everyone expects.
`no_such_file(N)` expands to nothing if there is no file named
`no_such_file` in the current directory. This is in line with the zsh
documentation and what everyone expects.
If your examples aren't artificial but really show what you are trying
to do, you can do it like this:
print -rC1 -- no_such_file(N)
This will print `no_such_file` if such file exists and will do nothing
otherwise.
If you really need that `ls` call (perhaps because you are passing
some flags to it), you can do this:
( ls -1 no_such_file(#q) ) 2>/dev/null
This does the same as above but about 1000 times slower and returns an
error if the file doesn't exist.
You can also use an explicit condition:
if [[ -e no_such_file ]]; then
ls -1 no_such_file
fi
Roman.
On 2021-01-29 7:33 a.m., Roman Perepelitsa wrote: > > `ls` without arguments lists files in the current directory. This is > mandated by POSIX and what everyone expects. Of course. > > `no_such_file(N)` expands to nothing if there is no file named > `no_such_file` in the current directory. This is in line with the zsh > documentation and what everyone expects. That's about what I I expected to hear. zsh can't be expected to feed 'ls' with something that duplicates a non-existent file, it can only remove the non-existent file thus leaving no argument thus ls must be 'ls *'. I had thought there might be some hidden mechanism by which ls might be informed that the given argument fails but I can quite understand that no such thing exists -- zsh just removes the non-existent argument and that's all she can do and ls is on it's own. Thanks Roman.
> On Jan 29, 2021, at 12:01 PM, Ray Andrews <rayandrews@eastlink.ca> wrote: > >> On 2021-01-29 7:33 a.m., Roman Perepelitsa wrote: >> >> `no_such_file(N)` expands to nothing if there is no file named >> `no_such_file` in the current directory. This is in line with the >> zsh documentation and what everyone expects. > > That's about what I I expected to hear. zsh can't be expected to > feed 'ls' with something that duplicates a non-existent file, it > can only remove the non-existent file thus leaving no argument This only happens because you're using '(N)', which you could easily drop if it's not desirable. It often is, though, so you need to be aware of how the rest of your code works if a glob expands to nothing. > thus ls must be 'ls *'. This is false. % mkdir -p foo/bar{1,2} && touch foo/bar{1,2}/baz && cd foo % ls bar1 bar2 % ls * bar1: baz bar2: baz You might be better off avoiding this sort of thing by testing your globs with `print` (or something similar), as Roman demonstrated. vq
On Fri, Jan 29, 2021 at 9:01 AM Ray Andrews <rayandrews@eastlink.ca> wrote:
>
> That's about what I expected to hear. zsh can't be expected to feed
> 'ls' with something that duplicates a non-existent file, it can only
> remove the non-existent file thus leaving no argument
Your problem is that (N) means NULL_GLOB, but you want it to mean CSH_NULL_GLOB.
Have you considered using "setopt CSH_NULL_GLOB" and then not using (N) ...?
On Fri, Jan 29, 2021 at 7:33 AM Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > print -rC1 -- no_such_file(N) > > This will print `no_such_file` if such file exists and will do nothing > otherwise. Not precisely nothing ... it will print a newline. > ( ls -1 no_such_file(#q) ) 2>/dev/null That can be done without a subshell: { ls no_such_file(#q) } 2>&- However, that needs one of extendedglob or nobareglobqual, plus I think he actually wants the error message. To get the effect of (#q) without extendedglob, use (+true) ... but I don't believe that's very useful in this specific example.
On 2021-01-29 9:52 a.m., Lawrence Velázquez wrote:
> mkdir -p foo/bar{1,2} && touch foo/bar{1,2}/baz && cd foo
Ah, right, I need 'ls -d *' to mirror plain 'ls'. Anyway the point
remains that ls has no way of knowing that zsh has removed the argument
thus there is no failure to report.
Have you considered using "setopt CSH_NULL_GLOB" and then not using (N) ...?
To avoid surprises it seems the ' 2> dev/null ' is going to satisfy. In unnecessary detail what was happening was that in my wrapper I'd get this:
1 /aWorking/Zsh/Source/Wk 3 $ l zzz
LISTING of "zzz": all file types, INsensitive. Sorting upside down by: Mod. Time:
drwxr-xr-x 10 20480 [2021-01-29--07:08] ./
Items found: 1
Total bytes in this directory: 2.8M
Total including subdirs: 12M
... there was always that annoying false find of 'dot'. But ' >2 /dev/null ' fixes it. BTW the 'Items found' comes from using 'wc' but that too reports one item even if the output is zero which seems strange but it's fixable:
1 /aWorking/Zsh/Source/Wk 3 $ . l; l zzz
LISTING of "zzz": all file types, INsensitive. Sorting upside down by: Mod. Time:
Nothing found
... so all's well.
On Fri, Jan 29, 2021 at 8:04 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Fri, Jan 29, 2021 at 7:33 AM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > print -rC1 -- no_such_file(N)
> >
> > This will print `no_such_file` if such file exists and will do nothing
> > otherwise.
>
> Not precisely nothing ... it will print a newline.
If the file doesn't exist, the command is equivalent to this:
print -rC1 --
This command doesn't print anything.
Roman.
[-- Attachment #1: Type: text/plain, Size: 787 bytes --] > On Jan 30, 2021, at 4:50 AM, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > On Fri, Jan 29, 2021 at 8:04 PM Bart Schaefer <schaefer@brasslantern.com <mailto:schaefer@brasslantern.com>> wrote: >> >> On Fri, Jan 29, 2021 at 7:33 AM Roman Perepelitsa >> <roman.perepelitsa@gmail.com <mailto:roman.perepelitsa@gmail.com>> wrote: >>> >>> print -rC1 -- no_such_file(N) >>> >>> This will print `no_such_file` if such file exists and will do nothing >>> otherwise. >> >> Not precisely nothing ... it will print a newline. > > If the file doesn't exist, the command is equivalent to this: > > print -rC1 -- > > This command doesn't print anything. % print -rC1 -- no_such_file(N) zsh 5.8 (Ubuntu): prints nothing zsh 5.7.1 (Mac): prints return [-- Attachment #2: Type: text/html, Size: 6118 bytes --]
On Fri, Jan 29, 2021 at 9:05 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Fri, Jan 29, 2021 at 7:33 AM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > ( ls -1 no_such_file(#q) ) 2>/dev/null
>
> That can be done without a subshell:
>
> { ls no_such_file(#q) } 2>&-
Why does >&- produce an error message when connected to a builtin,
rather than an external command?
% print -qqq
print: bad option: -q
% git -qqq
unknown option: -qqq
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
% print -qqq 2>&-
zsh: write error
% git -qqq 2>&-
%
And for the cases below, why does it produce an error message for the
former, but not for the latter?
% { print -qqq } 2>&-
zsh: write error
% { print no_such_file(#q); print -qqq } 2>&-
%
Is this an intended or unintended difference?