Skip to content

Instantly share code, notes, and snippets.

@mjf
Last active August 25, 2021 06:15
Show Gist options
  • Save mjf/4600960 to your computer and use it in GitHub Desktop.
Save mjf/4600960 to your computer and use it in GitHub Desktop.
PREEN - Preen current path by file type
#! /bin/sh
# PREEN - Preen current/working directory by file type
# Copyright (C) 2013,2018,2020 Matous J. Fialka, <https://mjf.cz/>
# Released under the terms of The MIT License
PREENDIR="${PREENDIR:-.preen}"
PREENRC="${PREENRC:-.preenrc}"
for util in which find file test mkdir ln
do
if ! which "$util" 1>/dev/null 2>/dev/null
then
echo "Fatal error: which(1) at \`$util'" 1>&2
exit 1
fi
done
if test -e "$PWD/$PREENDIR"
then
echo "Fatal error: path \`$PWD/$PREENDIR' must not exist" 1>&2
exit 1
fi
if test -e "$PWD/$PREENRC"
then
if ! source "$PWD/$PREENRC"
then
echo "Fatal error: source \`$PWD/$PREENRC'" 1>&2
exit 1
fi
fi
skipped=0
processed=0
failed=0
suspicious=0
maybe_dangerous=0
maybe_url=0
assorted=0
excluded=0
included=0
SIGNALS=(HUP USR1 USR2)
sighandler()
{
cat <<- EOT
STATISTICS
----------
Processed : $processed
Excluded : $excluded
Included : $included
Skipped : $skipped
Failed : $failed
Suspicious : $suspicious (dangerous: $maybe_dangerous, URL: $maybe_url)
Assorted : $assorted
TOTAL : $((skipped + failed + processed + suspicious + assorted))
EOT
sighandled=0
for sig in ${SIGNALS[@]}; do
if [ "$sig" = "$1" ]; then
sighandled=1
fi
done
if [ $sighandled -eq 0 ]; then
for sig in ${SIGNALS[@]}; do
trap - $sig
done
kill -$1 $$
exit $2
fi
}
siginit() {
for sig in ${SIGNALS[@]}; do
trap 'sighandler '$sig' $?' $sig
done
}
siginit
while read -r name
do
if ! type=`file -b --mime-type -e cdf "$name"` 2>/dev/null
then
echo "Fatal error: file(1) at \`$name'" 1>&2
failed=$((failed + 1))
continue
fi
if test "${type///}" = "${type}"
then
type="assorted/$type"
assorted=$((assorted + 1))
fi
case "$name" in
*[\*]*)
type="suspicious/maybe-dangerous/$type"
suspicious=$((suspicious + 1))
maybe_dangerous=$((maybe_dangerous + 1))
;;
*[%\?\&]*)
type="suspicious/maybe-url/$type"
suspicious=$((suspicious + 1))
maybe_url=$((maybe_url + 1))
;;
esac
if grep -q -E -i "$PREEN_EXCLUDE_REGEX" <<< "$type"
then
if grep -q -E -i -v "$PREEN_INCLUDE_REGEX" <<< "$type"
then
excluded=$((excluded + 1))
skipped=$((skipped + 1))
processed=$((processed + 1))
continue
else
included=$((included + 1))
fi
fi
if ! test -d "$PWD/$PREENDIR/$type"
then
if ! mkdir -p "$PWD/$PREENDIR/$type"
then
echo "Fatal error: mkdir(1) at \`$PWD/$PREENDIR/$type'" 1>&2
exit 1
fi
fi
if ! ln --backup=numbered -s "$name" "$PWD/$PREENDIR/$type/${name##*/}" 2>/dev/null
then
echo "Non-fatal error: skipped \`$name'" 1>&2
skipped=$((skipped + 1))
else
processed=$((processed + 1))
fi
done <<< "$(find "$PWD" -mount -name '.?*' -prune -o -follow -type f -print 2>/dev/null)"
sighandler 15 $?
# vi:ft=sh
@mjf
Copy link
Author

mjf commented Jan 23, 2013

USAGE

Use as simply as follows:

cd /some/path
preen
ls -R .preen

or, alternatively, as follows (see TODO)

cd /some/path
preen
cp -R -L .preen /backup/path

or, even, as follows (see TODO):

cd /some/path
preen
tar chf backup.tar .preen

or (see TODO):

cd /some/path
preen
rsync -a .preen /backup/path

STATISTICS

You can see runtime statistics by signaling the PID of the preen(1) process by one of HUP, USR1 or USR2. Run preen(1) in one terminal:

preen
STATISTICS
----------
Processed  : 123456
Excluded   : 0
Included   : 123400
Skipped    : 56
Failed     : 0
Suspicious : 5 (dangerous: 1, URL: 4)
Assorted   : 0
TOTAL      : 123456

and signal it from another terminal:

while true; do
  pkill -USR1 preen
  sleep 5
done

or, simply:

watch -n5 pkill -USR1 preen

Enjoy!

@mjf
Copy link
Author

mjf commented Jan 24, 2013

TODO

  • Handle dupes so that it makes sense with backuping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment