Summary: If there ever was a shell that expanded {}
, it's really old legacy stuff by now.
In the Bourne shell and in POSIX-compliant shells, braces ({
and }
) are ordinary characters (unlike (
and )
which are word delimiters like ;
and &
, and [
and ]
which are globbing characters). The following strings are all supposed to be printed literally:
$ echo { } {} {foo,bar} {1..3}
{ } {} {foo,bar} {1..3}
A word consisting of a single brace is a reserved word, which is only special if it is the first word of a command.
Ksh implements brace expansion as an incompatible extension to the Bourne shell. This can be turned off with set +B
. Bash emulates ksh in this respect. Zsh implements brace expansion as well; there it can be turned off with set +I
or setopt ignore_braces
or emulate sh
. None of these shells expand {}
in any case, even when it's a substring of a word (e.g. foo{}bar
), due to the common use in arguments to find
and xargs
.
Single Unix v2 notes that
In some historical systems, the curly braces are treated as control operators. To assist in future standardisation activities, portable applications should avoid using unquoted braces to represent the characters themselves. It is possible that a future version of the ISO/IEC 9945-2:1993 standard may require that {
and }
be treated individually as control operators, although the token {}
will probably be a special-case exemption from this because of the often-used find
{}
construct.
This note was dropped in subsequent versions of the standard; the examples for find
have unquoted uses of {}
, as do the examples for xargs
. There may have been historical Bourne shells where {}
had to be quoted, but they would be really old legacy systems by now.
The csh implementations I have at hand (OpenBSD 4.7, BSD csh on Debian, tcsh) all expand {foo}
to foo
but leave {}
alone.
You don't need to use awk
at all. Use the built-in tests that ksh
provides, something like this:
#!/bin/ksh
for NAME in *
do
FOUND=no
if [[ -d $NAME && $NAME != '.' && $NAME != '..' ]]
then
for SUBNAME in $NAME/*
do
if [[ -d $SUBNAME ]]
then
FOUND=yes
break
fi
done
if [[ $FOUND == no ]]
then
echo Found only files in $NAME
fi
fi
done
That little script looks in all the directories in the current directory, and tells you if they only contain files, no sub-directories.
Best Answer
You can throw away error reporting from
find
with2>/dev/null
, or you can avoid running the command at all:As a slight optimisation and clearer code, some versions of
find
- including yours - can perform therm
for you directly: