Estou usando o nsxiv para visualizar imagens JPEG e PNG no FreeBSD. No entanto, não consigo encontrar uma maneira de classificar e filtrar as imagens por hora de modificação para visualizá-las no nsxiv no FreeBSD. No Linux com GNU coreutils e GNU findutils, posso usar o comando abaixo para visualizar imagens modificadas após 01/10/2023, classificadas por horário de modificação.
find . -maxdepth 1 -type f \
\( -iregex '.+\.jpe?g$' -o -iregex '.+\.png$' \) \
-newermt 2023-10-01 \
-exec ls -t --zero -- {} + | \
nsxiv -0 -
Não consigo encontrar um comando equivalente no FreeBSD que seja capaz de lidar com nomes de arquivos que contenham espaços, novas linhas e outros caracteres incomuns. O problema é que o FreeBSD ls
não tem --zero
opção de gerar nomes de arquivos separados por NUL para canalizar para nsxiv
. Outro problema é que o FreeBSD find
não possui nenhum arquivo -printf0
que possa ser útil para obter tempos de modificação de arquivos que podem ser passados para sort -z
. Como classifico e filtro imagens por hora de modificação e as visualizo no nsxiv no FreeBSD?
Estou usando /bin/sh
(dash) no Linux e /bin/sh
no FreeBSD.
Você terá que passar por xargs corretamente para fazer a classificação; então, algo como
We use the "decorate – sort – undecorate" trick that you would normally find in languages with tuples. Here, we need to separate our sort key (the time in seconds since epoch,
%Y
in stat) from our value (the file name) with a space. And thencut
that back out. A bit awkward!If it is important for you to be able to make it work on a vanilla FreeBSD system there is another answer with find/xargs/cut/stat. If you are able to install additional utilities there is a cleaner answer using zsh as well.
But if you are used to GNUism and Linux then it is very easy to live a comfortable life on FreeBSD if you install the GNU findutils.
In the same vein people have got bitten by BSD ls, grep, make, sed and awk. But their GNU counterparts are easily available as well as gnuls, gnugrep, gmake, gsed and gawk. Are you going all in then get coreutils
They can all coexist with the BSD versions on your system. You will then typically prefix the command with a "g" for the GNU version:
gnuls
,gfind
,gxargs
,gmake
,gsed
andgawk
.And if you hate to prefix your beloved gnu variants then see "How to make GNU grep the default in FreeBSD?"
If you get used to the BSD variants instead then they are available on Linux as well. See bsdutils
You could do:
For portability + reliability,
perl
is likely your best bet:Note that your
-exec ls -t --zero -- {} +
won't work properly at sorting the files by modification time if the list of files is big enough thatfind
needs to invokels
several times.I have found a solution that works in FreeBSD's
/bin/sh
. I have tried it in FreeBSD 13.2. It seems to properly handle filenames that contain backslashes and whitespace (spaces, tabs, and newlines), including leading and trailing whitespace.How it works:
ls -l -B -D%s
-B
displays non-printable characters in octal notation. This is important for handling filenames that contain newlines and tabs.-D%s
formats file modification time in seconds since the Epoch. This will be useful for sorting by modification time.cut -w -f6-
: remove all columns from the output ofls -l ...
except the columns that contain file modification times and filenames.-w
is necessary to make consecutive spaces count as one delimiter.sort -r
: sort files by modification time from the most recently modified to the oldest.cut -f2-
: remove the column of file modification times, leaving only the (newline-separated) filenames.printf
's%b
format string to convert the octal notation in the filenames back to the actual characters (i.e. including newline and tabs). Separate the filenames using the NULL character (\0
), pipe the NULL-separated filenames intonsxiv -0 -
.Additional notes:
cut -w -f6- | sort -r | cut -f2-
cannot be replaced byls
's-t
option. As user "Stéphane Chazelas" wrote in another answer on this webpage:find ... \( -iregex '.\{1,\}\.jpe\{0,1\}g$' -o -iregex '.\{1,\}\.png$' \)
could be simplified by using extended regular expressions. e.g.find -E ... -iregex '.+\.(jpe?g|png)$'
.-n
option tols
, so thatls
outputs user ids and group ids instead of names.