diff --git a/install.sh b/install.sh index cbca969..1c5a9e0 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # rename-ext install script @@ -10,3 +10,12 @@ git clone --depth 1 \ ln -s $PREFIX/src/rename-ext/rename-ext.sh \ $PREFIX/bin/rename-ext + + +sudo apt-get install -y \ + jpegoptim \ + imagemagick \ + pngcrush \ + pngquant + +cargo install sd diff --git a/rename-only.sh b/rename-only.sh new file mode 100755 index 0000000..304d7e2 --- /dev/null +++ b/rename-only.sh @@ -0,0 +1,304 @@ +#!/usr/bin/env bash + +## rename-ext +# > changes file-extension based on mime-type + +## also +# - removes `*?|^:"<>` characters from the file-name +# - reducing multiple spaces, dots, and underscores +# - adds rename-date suffix to ensure uniquness of the filename +# - strips exec-flag from non-executive types (usual leftover from FAT/NTFS) +# - optimizes images while at it (shows reduction size in `kb` and `%`) + +## example +# rename-ext /Data/Pictures/_unsorted/**/* + +## requires +# - file - to determine file type +# - `cargo install sd` – better sed + +ALL_EXTS=`echo \ + 'gif|jpe?g|jp2|jfif|a?png|web(p|m)|svg + |eps|tga|tiff?|psd|ico|xcf|heic + |eot|otf|ttf|epub|doc|docx|xls|swf|pdf|odt + |flac|opus|ogg|m4a|wav + |mpe?g|mp\d|mov|mkv|avif?|asf|3gpp?|av1 + |html?|sh|py|php + ' \ + | tr -d '[:space:]' \ + ` + +mkdir -p ~/tmp + + +OPTIONS='' +CHX_CHANGELOG='' +NR='1' + + +calc_reduction() +{ + SIZE_PRE="$1" + SIZE_POST="$2" + PERECENT=` echo "scale=2; 100 - (100 * $SIZE_POST / $SIZE_PRE)" | bc ` + RESULT="$(( $SIZE_PRE / 1000 ))-$(( ( $SIZE_PRE - $SIZE_POST ) / 1000 )) kb \ +($PERECENT%) +" + echo "$RESULT" +} + + +ch_x() +{ + FILENAME="$1" + # echo "FILENAME = '$FILENAME'" + + CHX_CHANGELOG='' + + IS_X_INTENDED='0' + if [ ! -z "$2" ]; then + IS_X_INTENDED='1' + fi + # echo "IS_X_INTENDED = '$IS_X_INTENDED'" + + IS_X=`stat -c '%A' "$FILENAME" | grep 'x' | wc -l` + # echo "IS_X = '$IS_X'" + + MODE='-x' + if [[ '1' == "$IS_X_INTENDED" ]]; then + MODE='+x' + fi + # echo "MODE = '$MODE'" + + if [[ ! "$OPTIONS" =~ 'test-run' ]]; then + # echo '(not a test-run)' + if [[ ! "$OPTIONS" =~ 'only-ext' ]]; then + # echo '(not only-ext)' + if [[ ! "$IS_X" == "$IS_X_INTENDED" ]]; then + CHX_CHANGELOG="chmod $MODE" + fi + chmod "$MODE" "$FILENAME" + fi + fi +} + + +rename_ext() +{ + NAME="$1" + EXT="$2" + NOTE='' + TARGET='' + + ch_x "$FILENAME" + + if [[ "$OPTIONS" =~ 'only-ext' ]]; then + NAME_NO_EXT=` echo "$NAME" \ + | sd -f i "(\.+($ALL_EXTS))$" '' \ + ` + TARGET="$NAME_NO_EXT.$EXT" + else + if [[ ! "$OPTIONS" =~ 'test-run' ]]; then + + SIZE_PRE=` stat "$FILENAME" -c '%s' ` + + if [ 'png' = "$EXT" ]; then + mogrify "$FILENAME" + if [ -f "$FILENAME.tmp.png" ] \ + && [ -s "$FILENAME.tmp.png" ] + then + mv "$FILENAME.tmp.png" "$FILENAME" + else + rm "$FILENAME.tmp.png" + fi + fi + + SIZE_POST=` stat "$FILENAME" -c '%s' ` + + [ $SIZE_PRE -gt $SIZE_POST ] \ + && NOTE=` calc_reduction "$SIZE_PRE" "$SIZE_POST" ` + fi + DATE=` date -r "$NAME" -u "+%Y%m%d%H%M%S" ` + TCLEAN=` echo "$NAME" \ + | sd '[\\\?\*\|^:"<>]+' '_' \ + | sd '_\d{12,}\.' '.' \ + | sd -f i "(\.+($ALL_EXTS))+$" '' \ + ` + TARGET=` echo "${TCLEAN}_$DATE.$EXT" \ + | sd '([\s\.,_]){3,}' '$1' \ + ` + fi + + IS_SAME_NAME='0' + if [[ "$NAME" == "$TARGET" ]]; then + IS_SAME_NAME='1' + fi + # echo "IS_SAME_NAME = '$IS_SAME_NAME'" + + # echo "CHX_CHANGELOG = '$CHX_CHANGELOG'" + if [[ '1' == "$IS_SAME_NAME" ]] \ + && [ -z "$CHX_CHANGELOG" ] + then + return + fi + + echo "$NR:" + NR="$(($NR+1))" + echo " $FILENAME" + + if [ ! -z "$CHX_CHANGELOG" ]; then + echo " $CHX_CHANGELOG" + CHX_CHANGELOG='' + fi + + if [[ '1' == "$IS_SAME_NAME" ]]; then + return + fi + + + if [[ "$OPTIONS" =~ 'test-run' ]]; then + if [ -f "$TARGET" ]; then + if [[ "$PARAMS" =~ 'force-replace' ]]; then + echo " >> replacing existing file >>" + else + echo " !! file already exist !!" + fi + fi + echo "$TARGET" + else + if [ ! -f "$TARGET" ]; then + echo " >> $NOTE >>" + echo " $TARGET" + mv "$NAME" "$TARGET" + else + if [[ "$PARAMS" =~ 'force-replace' ]]; then + echo " >> $NOTE ## replacing existing file >>" + echo " $TARGET" + mv "$NAME" "$TARGET" + else + echo ' !! File already exist, use `--force-replace` to overwrite !! ' + echo " $TARGET" + fi + fi + fi + +} + +for PARAM in "$@"; do + # echo "PARAM = '$PARAM'" + if [[ '--only-ext' == "$PARAM" ]]; then + OPTIONS="$OPTIONS;only-ext" + # echo "OPTIONS = '$OPTIONS'" + elif [[ '--test-run' == "$PARAM" ]]; then + OPTIONS="$OPTIONS;test-run" + # echo "OPTIONS = '$OPTIONS'" + elif [[ '--force-replace' == "$PARAM" ]]; then + OPTIONS="$OPTIONS;force-replace" + # echo "OPTIONS = '$OPTIONS'" + fi +done + +[ ! -z "$OPTIONS" ] \ + && echo "OPTIONS: '$OPTIONS'" + + +# echo "@ = '$@'" +for FILENAME in "$@"; do + + # echo "FILENAME = '$FILENAME'" + + # NOT_F_=`[ ! -f "$FILENAME" ]` + # echo "NOT_F_ = '$NOT_F_'" + + # [ ! -f "$FILENAME" ] \ + # && continue + + FILE_TYPE=` file -b --mime-type "$FILENAME" ` + # echo "FILE_TYPE = '$FILE_TYPE'" + + case "$FILE_TYPE" in + + # pixel-based + 'image/gif') rename_ext "$FILENAME" 'gif' ;; + 'image/jpeg') rename_ext "$FILENAME" 'jpg' ;; + 'image/jp2') rename_ext "$FILENAME" 'jp2' ;; + 'image/png') rename_ext "$FILENAME" 'png' ;; + 'image/webp') rename_ext "$FILENAME" 'webp' ;; + 'image/avif') rename_ext "$FILENAME" 'avif' ;; + + # vector-based + 'image/svg+xml') rename_ext "$FILENAME" 'svg' ;; + 'image/x-eps') rename_ext "$FILENAME" 'eps' ;; + + # some less common image formats + 'image/heic') rename_ext "$FILENAME" 'heic' ;; + 'image/tiff') rename_ext "$FILENAME" 'tiff' ;; + 'image/vnd.adobe.photoshop') rename_ext "$FILENAME" 'psd' ;; + 'image/vnd.microsoft.icon') rename_ext "$FILENAME" 'ico' ;; + 'image/x-tga') rename_ext "$FILENAME" 'tga' ;; + 'image/x-xcf') rename_ext "$FILENAME" 'xcf' ;; + + # fonts + 'application/vnd.ms-fontobject') rename_ext "$FILENAME" 'eot' ;; + 'application/vnd.ms-opentype') rename_ext "$FILENAME" 'otf' ;; + 'font/sfnt') rename_ext "$FILENAME" 'ttf' ;; + + # documents + 'application/epub+zip') rename_ext "$FILENAME" 'epub' ;; + 'application/msword') rename_ext "$FILENAME" 'doc' ;; + 'application/pdf') ch_x "$FILENAME" ;; # can be .ai + 'application/vnd.ms-excel') rename_ext "$FILENAME" 'xls' ;; + 'application/vnd.oasis.opendocument.text') rename_ext "$FILENAME" 'odt' ;; + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') rename_ext "$FILENAME" 'docx' ;; + 'application/x-shockwave-flash') rename_ext "$FILENAME" 'swf' ;; + + # audio + 'audio/flac') rename_ext "$FILENAME" 'flac' ;; + 'audio/mpeg') rename_ext "$FILENAME" 'mp3' ;; + 'audio/ogg') rename_ext "$FILENAME" 'ogg' ;; + 'audio/x-m4a') rename_ext "$FILENAME" 'm4a' ;; + 'audio/x-wav') rename_ext "$FILENAME" 'wav' ;; + + # video + 'video/3gpp') rename_ext "$FILENAME" '3gp' ;; + 'video/av1') rename_ext "$FILENAME" 'avi' ;; + 'video/MP2T') rename_ext "$FILENAME" 'mp2' ;; + 'video/mp4') rename_ext "$FILENAME" 'mp4' ;; + 'video/quicktime') rename_ext "$FILENAME" 'mov' ;; + 'video/webm') rename_ext "$FILENAME" 'webm' ;; + 'video/x-m4v') rename_ext "$FILENAME" 'mp4' ;; + 'video/x-matroska') rename_ext "$FILENAME" 'mkv' ;; + 'video/x-ms-asf') rename_ext "$FILENAME" 'asf' ;; + + # text + 'application/json') ch_x "$FILENAME" ;; # can be any other language + 'text/html') ch_x "$FILENAME" ;; # can be .htm, .htc, .mht, ... + 'text/xml') ch_x "$FILENAME" ;; # can be .xml, .opml, .rss, ... + 'text/plain') ;; # can be any file with not enough text + 'text/x-python') ;; # can be .py, .py3, have no .ext + 'text/x-shellscript') ;; # can be .sh, .zsh, have no .ext + + # binady data + 'application/x-sqlite3') ch_x "$FILENAME" ;; # can be .db, .sql, .sq3 + + # special + 'application/octet-stream') ;; # can be anything + 'inode/directory') + # echo "$FILENAME is a folder" + # echo "about to ch_x" + ch_x "$FILENAME" '+' + ;; # a folder + 'inode/x-empty') ch_x "$FILENAME" ;; # zero-size + + # default + *) echo "?? $FILENAME : $FILE_TYPE" ;; + + esac + +done + +# if [[ "@#" -eq 1 ]]; then +# if [[ `file -b --mime-type "$1"` == "inode/directory" ]]; then +# find "$1" +# fi +# fi