Is that size as in file size, or size as in image dimensions?
In zsh, to see all .png
files in the current directory and its subdirectories, sorted by increasing file size:
echo **/*.png(oL)
There's no convenient glob qualifier for grabbing every N files. Here's a loop that sets the array $a
to contain every 50th file (starting with the largest).
a=() i=0
for x in **/*.png(OL); do
((i%50)) || a+=$x
((++i))
done
my-favorite-image-viewer $a
Without zsh or GNU find, there's no easy way of sorting find
output by metadata (there's find -ls
or find -exec ls
or find -exec stat
, but they might not work with files containing non-printable characters, so I don't like to recommend them). Here's a way to do it in Perl.
find . -name '*.png' |
perl -e '
$, = "\n"; # separate elements by newlines in the output
print # print…
sort {-s $a <=> -s $b} # …sorted by file size…
map {chomp;$_} <> #…the input lines (with the newline bitten off)
'
And here's a way to view every 50th file (starting with the largest):
find . -name '*.png' |
perl -e '
$, = "\n";
exec "my-favorite-image-viewer",
map {$i++ % 50 ? () : $_} # every 50
sort {-s $b <=> -s $a} map {chomp;$_} <>
'
Another approach would be to create symbolic links in a single directory, with names ordered by file size. In zsh:
mkdir tmp && cd tmp
i=1000000 # the extra 1 on the left ensures alignment
for x in ../**/*(oL); do
((++i))
ln -s $x ${i#1}.png
done
With Perl:
mkdir tmp && cd tmp
find .. -name '*.png' |
perl -e '
$, = "\n";
for $x (sort {-s $a <=> -s $b} map {chomp;$_} <>) {
symlink $x, sprintf("%06d", ++$i);
}
'
The shell has a built-in variable expansion field separator. So if you have a string and your delimiter is solid you can do:
var=32768,'dff0207a-591f-4435-9f8b-7b9b3e6ba2c1','d1f77359b3f7236806489ba3108c771f','NUMBER','US_EN','LATIN','GREEK','GERMAN'
( IFS=,; set -f
for field in $var
do printf '\n%s\n\t' "$field - md5:" >&2
printf %s "$field" |
md5sum
done |
cut -d\ -f1
)
32768 - md5:
f43764367fa4b73ba947fae71b0223a4
dff0207a-591f-4435-9f8b-7b9b3e6ba2c1 - md5:
0983e6c45209f390461c1b1df9320674
d1f77359b3f7236806489ba3108c771f - md5:
07d82ab57ba81f991ab996bd7c5a0441
NUMBER - md5:
34f55eca38e0605a84f169ff61a2a396
US_EN - md5:
c9d3e580b7b102e864d9aea8703486ab
LATIN - md5:
0e869135050d24ea6e7a30fc6edbac6c
GREEK - md5:
d4cacc28e56302bcec9d7af4bba8c9a7
GERMAN - md5:
ed73cca110623766d7a2457331a4f373
That should give you a newline separated list of md5s - as it did me.
IFS=,
is used to specify that when any variable type shell expansion is performed the shell should split it out on the ,
character rather than <space><newline><tab>
- which is the default. set -f
is used to specify that if the shell should encounter any file globs within an unquoted expansion it should not expand them - so echo *
would print only *
regardless of the contents of the current directory.
For every comma separated field in $var
the shell does printf "$field" | md5sum
- so once per field without separator strings as I take the question to mean. And last cut
trims the few spaces and the -
at the end of each output line as it receives them. Most of the output is actually to stderr
- cut
only ever sees the md5sums
.
Best Answer
Have you considered the
dd
command? It lets you skip any number of bytes, then output any number of bytes.dd
, input file name, block size 1, skip first sk bytes of input file, then copy ct bytes to stdout (or specify a file withof=name
). Redirect error messages to avoid the status messages it usually prints at the end.