Finding recent work directories
Since I often get side-tracked and forget what I was doing, I wrote a script to find directories with recent (or otherwise selected) files in them. That makes a better list than sorting directories by their own modification times. This script, 'finddirs_by_latest_file', allows to restrict the search with extra find expression terms, but I usually just run the second script below, 'fblf100', which invokes finddirs_by_latest_file to make two lists; for the latest 5 and 100 days (or whatever time periods given). Excuse all the script boilerplate. Carlos, this may help you find your router config info. --<cut>------------------------------------------------------------------ #!/bin/sh # finddirs_by_latest_file.sh 2022-06-30 rw # # Outputs a list of directories of found files, sorted by the time of # their most recently modified file, and prefixed by a file count. #-----<lib/s/template-errx-getopts.sh>----------------------------------- CMD=finddirs_by_latest_file VERSION=0.1 export LC_COLLATE='C' Cmd=`basename "$0"` umsg() { #------<USAGE>--------------------------------------------------------- printf 'usage: %s %s\n' \ "$Cmd" '[--sdir] [find_options] <find_starting_point>... [find_expression]' \ '' '' \ 'The' 'find_expression, if any, is prepended to an implied:' \ ' -type f' '-exec...' } errmsg() { # usage: errmsg [msg_line ...] test 1 -le "$#" || return 0 printf "${Cmd}: %s\\n" "$@" >&2 } usage() { # for output to stderr, and error exit: usage [msg_line ...] # for normal exit: usage help if [ x"$*" = x'help' ] ;then umsg ;exit else errmsg "$@" ;umsg >&2 ;exit 2 fi } errx() { # usage: errx <exitcode> [msg_line ...] if expr x"${1-}" : x'[1-9][0-9]*$' > /dev/null ;then ExCode="$1" ;shift else ExCode=3 ;set -- "$@" "$BUG: errx(): missing exit code" fi errmsg "$@" ;exit "$ExCode" } BUG="error: software bug" errxbug() { errx 3 "$BUG: $@" } exists() { # usage: exists <path> test -e "${1:?'exists(): null or missing arg'}" || test -h "$1" # test -f "${1:?'exists(): null or missing arg'}" || test -d "$1" \ # || test -h "$1" || test -b "$1" || test -c "$1" || test -p "$1" } #------------------------------------------------------------------------ # Option defaults SORT_BY_DIR_f=false #XXX HACK: '--sdir' option is only recognized when it is first if [ x"${1-}" = x'--sdir' ] ;then SORT_BY_DIR_f=true shift fi GOPTSTRING='hV' while getopts ":$GOPTSTRING" OPT ;do case "$OPT" in #----- h) usage help ;; V) printf 'RW %s %s\n' "$CMD" "$VERSION" ;exit ;; :) usage "missing argument for option: ${OPTARG}" ;; \?) usage "invalid option: ${OPTARG}" ;; *) errxbug "getopts optstring: option: ${OPT}" ;; esac done shift `expr $OPTIND - 1` if [ x"$SORT_BY_DIR_f" = x'true' ] ;then sort_by() { sort -k 3 -k 2,2n ;} else # sort by time, then by dir (default) sort_by() { sort -k 2,2n -k 3 ;} fi #------------------------------------------------------------------------ W=' *[^ ][^ ]* ' # find files: stat <seconds_since_Epoch> <path> # sed: truncate last path component (to parent dir), use '.' if empty, # or '/' if at root # sort by dir, then by recent to old # uniq: most recent of each dir. prefix with file count # sort by time, then by dir (unless '--sdir' option: sort by dir) # sed: remove seconds field export TMPDIR=~/tmp TEMPF=`mktemp --tmpdir "$CMD.XXXXXXXXXX.temp"` \ && trap 'rm -f -- "$TEMPF"' EXIT \ || exit find -H "$@" -type f -exec stat -c '%Y %n' {} + > "$TEMPF" || exit sed -e ' s+^\('"$W"'\)[^/]*$+\1.+ t s+^\('"$W"'/\)[^/]*$+\1+ t s+^\('"$W"'.*\)/[^/]*$+\1+ ' "$TEMPF" \ |sort -k 2 -k 1,1nr \ |uniq -c -f 1 \ |sort_by \ |sed -e 's+'"$W"'+ +2' --<cut>------------------------------------------------------------------ --<cut>------------------------------------------------------------------ #!/bin/sh # fblf100 2021-12-07 rw TOP=~ usage() { printf 'usage: fblf100 [#_by_time_days [#_by_path_days]]' >&2 exit 2 } { printf '=== %s days, in order\n' "${1:-5}" finddirs_by_latest_file "$TOP" -mtime -"${1:-5}" \ || usage printf '\n=== %s days, sorted\n' "${2:-100}" finddirs_by_latest_file --sdir "$TOP" -mtime -"${2:-100}" \ || usage } \ |less --<cut>------------------------------------------------------------------ -- Robert Webb
I forget too, but OFMs remember for me: $ cat ~/config/mc/mc.keymap [filemanager] History = alt-shift-h [panel] History = alt-h $ In fcl, directory history is Alt-Shift-F8. http://silk.apana.org.au/rpm-opensuse15-unstable-dev is Leap repo URI for fcl. -- Evolution as taught in public schools is, like religion, based on faith, not based on science. Team OS/2 ** Reg. Linux User #211409 ** a11y rocks! Felix Miata
On Tue, 28 Feb 2023 19:18:41 -0500, Felix Miata <mrmazda@earthlink.net> wrote:
I forget too, but OFMs remember for me:
$ cat ~/config/mc/mc.keymap [filemanager] History = alt-shift-h
[panel] History = alt-h $
In fcl, directory history is Alt-Shift-F8. http://silk.apana.org.au/rpm-opensuse15-unstable-dev is Leap repo URI for fcl.
Which brings to mind: Is there a history available for whatever screenshot tool Carlos used to capture his router configuration? Maybe screenshots should get logged to the journal. -- Robert Webb
On 2023-03-01 02:12, Robert Webb wrote:
On Tue, 28 Feb 2023 19:18:41 -0500, Felix Miata <mrmazda@earthlink.net> wrote:
I forget too, but OFMs remember for me:
$ cat ~/config/mc/mc.keymap [filemanager] History = alt-shift-h
[panel] History = alt-h $
In fcl, directory history is Alt-Shift-F8. http://silk.apana.org.au/rpm-opensuse15-unstable-dev is Leap repo URI for fcl.
What is fcl?
Which brings to mind: Is there a history available for whatever screenshot tool Carlos used to capture his router configuration? Maybe screenshots should get logged to the journal.
I used XFCE applet "screenshot", or perhaps I used print page to PDF in Firefox. I just checked both. I have a directory dedicated to screenshots, and it is not there, but I'll check again this instant ... no, not there. The PDFs go to {home}, so I'll look there now (ls -ltr | grep -i .pdf). Nope, the last pdf there is dated 2020. I must check the laptop, maybe it is there. Maybe I printed to paper? Would be ridiculous, but possible. Looking in cups at completed jobs... nah, no info there, just print job numbers, sizes, dates. (I will have a look at your scripts after tea has made some effect, thanks ;-) ) I also have saved config files from the router, and they are text files. Not easy to parse, but definitely possible. -- Cheers / Saludos, Carlos E. R. (from 15.4 x86_64 at Telcontar)
On 2023-03-01 12:07, Carlos E. R. wrote:
On 2023-03-01 02:12, Robert Webb wrote:
On Tue, 28 Feb 2023 19:18:41 -0500, Felix Miata <> wrote:
Which brings to mind: Is there a history available for whatever screenshot tool Carlos used to capture his router configuration? Maybe screenshots should get logged to the journal.
I used XFCE applet "screenshot", or perhaps I used print page to PDF in Firefox. I just checked both. I have a directory dedicated to screenshots, and it is not there, but I'll check again this instant ... no, not there. The PDFs go to {home}, so I'll look there now (ls -ltr | grep -i .pdf). Nope, the last pdf there is dated 2020.
I must check the laptop, maybe it is there.
Maybe I printed to paper? Would be ridiculous, but possible. Looking in cups at completed jobs... nah, no info there, just print job numbers, sizes, dates.
Yes, I printed it to paper, just found the paper. :-} And it was just beside the computer, but below 4 other printouts. The place closest to me where it shouldn't get lost, the honor place. -- Cheers / Saludos, Carlos E. R. (from 15.4 x86_64 at Telcontar)
On Wed, Mar 1, 2023 at 12:07 PM Carlos E. R. <robin.listas@telefonica.net> wrote:
On 2023-03-01 02:12, Robert Webb wrote:
On Tue, 28 Feb 2023 19:18:41 -0500, Felix Miata <mrmazda@earthlink.net> wrote:
I forget too, but OFMs remember for me: In fcl, directory history is Alt-Shift-F8. http://silk.apana.org.au/rpm-opensuse15-unstable-dev is Leap repo URI for fcl. What is fcl?
apparently file commander at:
<http://silk.apana.org.au/> by Brian Havard
From: Robert Webb <webbdg@verizon.net> Date: Tue, 28 Feb 2023 23:31:57 +0000 (UTC) Since I often get side-tracked and forget what I was doing, I wrote a script to find directories with recent (or otherwise selected) files in them . . . For grins, I wrote a variation on this in Perl. Enjoy, -- Bob Rogers http://www.rgrjr.com/ #!/usr/bin/perl # # [created, based on finddirs_by_latest_file.sh by Robert Webb, as posted to # users@lists.opensuse.org. -- rgr, 28-Feb-23.] # use strict; use warnings; use Getopt::Long; my $sort_by_dir; my @find_opts; GetOptions('sdir!' => \$sort_by_dir, (map { ("$_=i" => \&find_opt); } qw(amin atime ctime cmin gid inum links mtime mmin uid)), (map { ("$_=s" => \&find_opt); } qw(anewer cnewer fstype group ilname iname ipath iregex iwholename), qw(lname name newer path perm regex samefile size user))) or usage(); ### Subroutines. sub usage { # Print a usage message & exit. warn "Usage: $0 [ --sdir ] [ <find-opts> ] [ <target-dirs> ]\n"; exit(0); } sub find_opt { # Store a "find" option after GetOptions has taken it off of @ARGV. my ($opt, $value) = @_; push(@find_opts, "-$opt" => $value); } ### Main code. unshift(@ARGV, '.') unless @ARGV; my $find_command = join(' ', 'find', @ARGV, @find_opts, q{-type f -print}); open(my $find, "$find_command |") or die "$0: Could not pipe from '$find_command': $!"; my %directory_file_count; while (<$find>) { next if m@/[.](git|svn)/@; s@[^/]+$@@; $directory_file_count{$_}++; } my @dirs = keys(%directory_file_count); for my $directory ($sort_by_dir ? sort(@dirs) : @dirs) { printf("%7d %s\n", $directory_file_count{$directory}, $directory); }
On Tue, 28 Feb 2023 17:46:54 -0800, Bob Rogers <rogers@rgrjr.com> wrote:
From: Robert Webb <webbdg@verizon.net> Date: Tue, 28 Feb 2023 23:31:57 +0000 (UTC) Since I often get side-tracked and forget what I was doing, I wrote a script to find directories with recent (or otherwise selected) files in them . . .
For grins, I wrote a variation on this in Perl. Enjoy, [attached (inline): finddirs_by_latest_file.pl]
Very cool. I've been enjoying studying it and learning some Perl. I used Perl a little bit a long time ago. Interesting. -- Robert Webb
On 3/1/23 00:31, Robert Webb wrote:
find -H "$@" -type f -exec stat -c '%Y %n' {} + > "$TEMPF" || exit
sed -e ' s+^\('"$W"'\)[^/]*$+\1.+ t s+^\('"$W"'/\)[^/]*$+\1+ t s+^\('"$W"'.*\)/[^/]*$+\1+ ' "$TEMPF" \ |sort -k 2 -k 1,1nr \ |uniq -c -f 1 \ |sort_by \ |sed -e 's+'"$W"'+ +2'
I didn't check what the part with uniq and sort_by is doing exactly. Still a minor hint: There's no need to call stat(1) again - because find(1) already has stat(3)-ed the file, and the -printf option allows to output the same information. This is a similar case than in the find manual (sorry if split on the next line): https://www.gnu.org/software/findutils/manual/html_node/find_html/Updating-A... stat(1): %Y time of last data modification, seconds since Epoch %n file name find(1): %p File's name. %Tk File's last modification time in the format specified by k, which is the same as for %A. and with k = '@': @ seconds since Jan. 1, 1970, 00:00 GMT, with fractional part. This makes something like this - which shows the 5 newest files: $ find -type f -printf '%T@:%p\n' | sort -k1,1n | tail -n5 | cut -d: -f 2- | xargs ls -ldog Of course, that only works for file names without newline '\n' in them, but that's a different discussion. Have a nice day, Berny
On Sat, 4 Mar 2023 09:42:02 +0100, Bernhard Voelker <mail@bernhard-voelker.de> wrote:
On 3/1/23 00:31, Robert Webb wrote:
find -H "$@" -type f -exec stat -c '%Y %n' {} + > "$TEMPF" || exit
sed -e ' s+^\('"$W"'\)[^/]*$+\1.+ t s+^\('"$W"'/\)[^/]*$+\1+ t s+^\('"$W"'.*\)/[^/]*$+\1+ ' "$TEMPF" \ |sort -k 2 -k 1,1nr \ |uniq -c -f 1 \ |sort_by \ |sed -e 's+'"$W"'+ +2'
I didn't check what the part with uniq and sort_by is doing exactly.
It is complicated because the end result I want is a list of directories, but they need to be selected and ordered based on the files they contain. So the find looks for files meeting the search terms and outputs their modification times and paths. I don't actually care about the filenames, so the first sed truncates them to just the directory path, and then there are multiple lines of the same directory paired with a modification time for each of the selected files within it. The first sort groups all the entries for the same directory together, and with the most recent modification time listed first. Then uniq chooses just that first one, so now there is one entry for each directory, paired with the mod time of the most recent file contained in it (what I was probably working on last). The second sort is to optionally sort the results either by path or mod times, and the final sed removes the time field that was just used for sorting.
Still a minor hint:
There's no need to call stat(1) again - because find(1) already has stat(3)-ed the file, and the -printf option allows to output the same information.
Yes. I'm surprised I overlooked the -printf option of find. I have used stat in find many times to get selected info displayed, and just ignored -printf. Thanks.
This is a similar case than in the find manual (sorry if split on the next line): https://www.gnu.org/software/findutils/manual/html_node/find_html/Updating-A...
stat(1): %Y time of last data modification, seconds since Epoch %n file name
find(1): %p File's name. %Tk File's last modification time in the format specified by k, which is the same as for %A.
and with k = '@': @ seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.
This makes something like this - which shows the 5 newest files:
$ find -type f -printf '%T@:%p\n' | sort -k1,1n | tail -n5 | cut -d: -f 2- | xargs ls -ldog
Useful. I'll be changing the script.
Of course, that only works for file names without newline '\n' in them, but that's a different discussion.
Yep. That's a bug. Not a feature. Let's see if I ever fix that. :-) -- Robert Webb
participants (6)
-
Bernhard Voelker
-
Bob Rogers
-
cagsm
-
Carlos E. R.
-
Felix Miata
-
Robert Webb