On 2023-12-25 19:53, Kaz Kylheku wrote:
> There are ways to speed it up by taking advantage of the contents of
> the * expansions being sorted. We change the requirements to this:
> we look for situations when the command line contains, as a contiguous
> subsequence, the sequence produced by *.
Like this, which is much faster; it takes about 0.14s in a directory of 2834
files,
where the previous one would take numerous seconds.
cat()
{
local -a orig_args=("$@")
local -a star_files=(*)
local star_seq_present=
local found=
local i
local j
# Crudely skip arguments that look like options
while true; do
case "$1" in
-* | --* ) shift ;;
* ) break ;;
esac
done
# get remaining args into args array
local -a args=("$@")
# determine whether star_files is a substring of orig_args
if [ ${#args[@]} -ge ${#star_files[@]} ] ; then
for (( i = 0; i <= ${#args[@]} - ${#star_files[@]}; i++ )); do
found=y
for (( j = 0; j < ${#star_files[@]}; j++ )); do
if [ "${args[$((i + j))]}" != "${star_files[$j]}" ] ; then
found=
break
fi
done
if [ $found ] ; then
star_seq_present=y
break
fi
done
fi
if [ $star_seq_present ] ; then
echo "cat: match for * present in command line!" 1>&2
return 1
fi
command cat "${orig_args[@]}"
}
Here is what a couple of tests look like:
$ cat *
cat: match for * present in command line!
!1!
$ cat * *
cat: match for * present in command line!
!1!
$ cat abc * def
cat: match for * present in command line!
!1!
$ cat cat.sh | head -4
cat()
{
local -a orig_args=("$@")
local -a star_files=(*)
The !1! is a thing in my personal environment: when a command indicates
a failed or abnormal termination, the status is printed between ! symbols.