strm_1st_last() ( unset l i c n
l=1 i='i\\\\' c='c\\\\' n='\
'; eval "echo |sed -n \":b
/[^[:blank:]]/h;$( wc -l "$@" |
sed -e '${1!d' -e "};s/[\"\/]/\\\\&/g
s/^[ 0]*\([^ 0-9]\)/1$i$n empty: \1/;/\n/b
s|^ *\([0-9]\{1,\}\) *\(.*\)|\\
\$((1+(l+=\\1)-\\1)){$i$n\\2$n :l\\
s/.*[^[:blank:]]/ \\&/p;//h;t\\
n;\$((l-1)){ //bb$n//!$c$n\ALL BLANK$n};bl$n}\\
\${l}{ x;s/^/ /p;s/.*//;x;d$n}|")"'" - "$@"'
)
That is a function which relies on one sed
process to build a workable script for a second. Well, it does not just rely on a sub-shelled sed
, but also wc
to first get the total line numbers for each of its arguments, and the shell itself to tally usably the arithmetic expressions sed
builds as line references for the second sed
.
Basically it handles all arguments as a single stream. For example, if you do:
seq 10 > file1; seq 5 > file2; sed -n \$= file[12]
sed
will print...
15
...because it automatically concatenates all filename arguments into a single data stream. So we just work with that.
First wc
is asked for a report on all of their lengths, and then sed
goes to work moulding that into a workable input script for a second sed
.
If wc
reports any of the files to have 0 lines sed
will print empty :filename for it and all others before anything else. (probably just 0 lines would be more accurate, though).
If, while scanning a section of input lines that comprises an entire file sed
encounters no non-blank characters at all, sed
will report it ALL BLANK (which is the only type of line report that is not indented)
For all other cases, sed
prints the first and last non-blank lines for each of its arguments and precedes each indented pair with the non-indented filename. This does not handle filenames containing newlines - though it probably wouldn't require much more to do it.
So if I do...
strm_1st_last file[12]
file1
1
10
file2
1
5
or...
: >file2; strm_1st_last file[12]
empty: file2
file1
1
10
...or...
strm_1st_last ~/*.sh
empty: /home/mikeserv/alleq.sh
empty: /home/mikeserv/mansed5.sh
/home/mikeserv/chrome.sh
#!/bin/bash
) &
/home/mikeserv/crap.sh
ALL BLANK
/home/mikeserv/getopts.sh
c=$# t=\ l='
done; printf '%s\n' "'${str#?}'"; done
/home/mikeserv/mansedmaybe.sh
mansed () {
);}
/home/mikeserv/mansed.sh
mansed () {
);}
/home/mikeserv/pr_after.sh
pr_after() if _i= _o=D OPTIND=1 _n='\
fi
/home/mikeserv/script.sh
#!/usr/bin/sh
echo done
/home/mikeserv/serial.sh
sq() ( IFS=\' set -f
# a b
/home/mikeserv/your_config.sh
zifs() { eval "shift ${3+3}
)
/home/mikeserv/ytplay.sh
ytplay() (
)
/home/mikeserv/zifs.sh
zifs() { eval "shift ${3+3}
)
cp -p
cp -a
orcp -p
should preserve the timestamp.