├── META-INF └── com │ └── google │ └── android │ ├── update-binary │ └── updater-script ├── README.md ├── common └── functions.sh ├── customize.sh ├── module.prop ├── system └── product │ └── overlay │ └── A12_VolumeAdjustmentOverlay │ └── A12VolumeAdjustmentOverlay.apk └── uninstall.sh /META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # Global vars 10 | TMPDIR=/dev/tmp 11 | PERSISTDIR=/sbin/.magisk/mirror/persist 12 | 13 | rm -rf $TMPDIR 2>/dev/null 14 | mkdir -p $TMPDIR 15 | 16 | # echo before loading util_functions 17 | ui_print() { echo "$1"; } 18 | 19 | require_new_magisk() { 20 | ui_print "*******************************" 21 | ui_print " Please install Magisk v19.0+! " 22 | ui_print "*******************************" 23 | exit 1 24 | } 25 | 26 | is_legacy_script() { 27 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh 28 | return $? 29 | } 30 | 31 | print_modname() { 32 | local len 33 | len=`echo -n $MODNAME | wc -c` 34 | len=$((len + 2)) 35 | local pounds=`printf "%${len}s" | tr ' ' '*'` 36 | ui_print "$pounds" 37 | ui_print " $MODNAME " 38 | ui_print "$pounds" 39 | ui_print "*******************" 40 | ui_print " Powered by Magisk " 41 | ui_print "*******************" 42 | } 43 | 44 | ############## 45 | # Environment 46 | ############## 47 | 48 | OUTFD=$2 49 | ZIPFILE=$3 50 | 51 | mount /data 2>/dev/null 52 | 53 | # Load utility functions 54 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 55 | . /data/adb/magisk/util_functions.sh 56 | [ $MAGISK_VER_CODE -gt 18100 ] || require_new_magisk 57 | 58 | # Preperation for flashable zips 59 | setup_flashable 60 | 61 | # Mount partitions 62 | mount_partitions 63 | 64 | # Detect version and architecture 65 | api_level_arch_detect 66 | 67 | # Setup busybox and binaries 68 | $BOOTMODE && boot_actions || recovery_actions 69 | 70 | ############## 71 | # Preparation 72 | ############## 73 | 74 | # Extract prop file 75 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 76 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" 77 | 78 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules 79 | MODULEROOT=$NVBASE/$MODDIRNAME 80 | MODID=`grep_prop id $TMPDIR/module.prop` 81 | MODPATH=$MODULEROOT/$MODID 82 | MODNAME=`grep_prop name $TMPDIR/module.prop` 83 | 84 | # Create mod paths 85 | rm -rf $MODPATH 2>/dev/null 86 | mkdir -p $MODPATH 87 | 88 | ########## 89 | # Install 90 | ########## 91 | 92 | if is_legacy_script; then 93 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 94 | 95 | # Load install script 96 | . $TMPDIR/install.sh 97 | 98 | # Callbacks 99 | print_modname 100 | on_install 101 | 102 | # Custom uninstaller 103 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh 104 | 105 | # Skip mount 106 | $SKIPMOUNT && touch $MODPATH/skip_mount 107 | 108 | # prop file 109 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop 110 | 111 | # Module info 112 | cp -af $TMPDIR/module.prop $MODPATH/module.prop 113 | 114 | # post-fs-data scripts 115 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh 116 | 117 | # service scripts 118 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh 119 | 120 | ui_print "- Setting permissions" 121 | set_permissions 122 | else 123 | print_modname 124 | 125 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 126 | 127 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then 128 | ui_print "- Extracting module files" 129 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 130 | 131 | # Default permissions 132 | set_perm_recursive $MODPATH 0 0 0755 0644 133 | fi 134 | 135 | # Load customization script 136 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh 137 | fi 138 | 139 | # Handle replace folders 140 | for TARGET in $REPLACE; do 141 | ui_print "- Replace target: $TARGET" 142 | mktouch $MODPATH$TARGET/.replace 143 | done 144 | 145 | if $BOOTMODE; then 146 | # Update info for Magisk Manager 147 | mktouch $NVBASE/modules/$MODID/update 148 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop 149 | fi 150 | 151 | # Copy over custom sepolicy rules 152 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then 153 | ui_print "- Installing custom sepolicy patch" 154 | PERSISTMOD=$PERSISTDIR/magisk/$MODID 155 | mkdir -p $PERSISTMOD 156 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule 157 | fi 158 | 159 | # Remove stuffs that don't belong to modules 160 | rm -rf \ 161 | $MODPATH/system/placeholder $MODPATH/customize.sh \ 162 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null 163 | 164 | ############## 165 | # Finalizing 166 | ############## 167 | 168 | cd / 169 | $BOOTMODE || recovery_cleanup 170 | rm -rf $TMPDIR 171 | 172 | ui_print "- Done" 173 | exit 0 174 | -------------------------------------------------------------------------------- /META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-12-Speaker-Group-Volume-Adjustment-Fix 2 | A Magisk Module that contains an overlay to reenable volume adjustments for speaker groups on Pixel phones running the January 2022 release. 3 | 4 | For more information, [read this article](https://blog.esper.io/android-12-cast-volume-changes-explained). 5 | -------------------------------------------------------------------------------- /common/functions.sh: -------------------------------------------------------------------------------- 1 | ########################################################################################## 2 | # 3 | # MMT Extended Utility Functions 4 | # 5 | ########################################################################################## 6 | 7 | abort() { 8 | ui_print "$1" 9 | rm -rf $MODPATH 2>/dev/null 10 | cleanup 11 | rm -rf $TMPDIR 2>/dev/null 12 | exit 1 13 | } 14 | 15 | cleanup() { 16 | rm -rf $MODPATH/common 2>/dev/null 17 | ui_print " " 18 | ui_print " **************************************" 19 | ui_print " * MMT Extended by Zackptg5 @ XDA *" 20 | ui_print " **************************************" 21 | ui_print " " 22 | $DEBUG && debug_log 23 | } 24 | 25 | debug_log() { 26 | set +x 27 | echo -e "***---Device Info---***" > $LOGFILE-tmp.log 28 | echo -e "\n---Props---\n" >> $LOGFILE-tmp.log 29 | getprop >> $LOGFILE-tmp.log 30 | echo -e "\n\n***---Magisk Info---***" >> $LOGFILE-tmp.log 31 | echo -e "\n---Magisk Version---\n\n$MAGISK_VER_CODE" >> $LOGFILE-tmp.log 32 | echo -e "\n---Installed Modules---\n" >> $LOGFILE-tmp.log 33 | ls $NVBASE/modules >> $LOGFILE-tmp.log 34 | echo -e "\n---Last Magisk Log---\n" >> $LOGFILE-tmp.log 35 | cat /cache/magisk.log >> $LOGFILE-tmp.log 36 | echo -e "\n\n***---MMT Extended Debug Info---***" >> $LOGFILE-tmp.log 37 | if [ -d "$MODPATH" ]; then 38 | echo -e "\n---Installed Files---\n" >> $LOGFILE-tmp.log 39 | grep "^+* cp_ch" $LOGFILE.log | sed 's/.* //g' >> $LOGFILE-tmp.log 40 | sed -i -e "\|$TMPDIR/|d" -e "\|$MODPATH|d" $LOGFILE-tmp.log 41 | find $MODPATH -type f >> $LOGFILE-tmp.log 42 | echo -e "\n---Installed Boot Scripts---\n" >> $LOGFILE-tmp.log 43 | grep "^+* install_script" $LOGFILE.log | sed -e 's/.* //g' -e 's/^-.* //g' >> $LOGFILE-tmp.log 44 | echo -e "\n---Installed Prop Files---\n" >> $LOGFILE-tmp.log 45 | grep "^+* prop_process" $LOGFILE.log | sed 's/.* //g' >> $LOGFILE-tmp.log 46 | fi 47 | echo -e "\n---Shell & MMT Extended Variables---\n" >> $LOGFILE-tmp.log 48 | (set) >> $LOGFILE-tmp.log 49 | echo -e "\n---(Un)Install Log---\n" >> $LOGFILE-tmp.log 50 | echo "$(cat $LOGFILE.log)" >> $LOGFILE-tmp.log 51 | mv -f $LOGFILE-tmp.log $LOGFILE.log 52 | } 53 | 54 | device_check() { 55 | local PROP=$(echo "$1" | tr '[:upper:]' '[:lower:]') 56 | for i in /system /vendor /odm /product; do 57 | if [ -f $i/build.prop ]; then 58 | for j in "ro.product.device" "ro.build.product" "ro.product.vendor.device" "ro.vendor.product.device"; do 59 | [ "$(sed -n "s/^$j=//p" $i/build.prop 2>/dev/null | head -n 1 | tr '[:upper:]' '[:lower:]')" == "$PROP" ] && return 0 60 | done 61 | fi 62 | done 63 | return 1 64 | } 65 | 66 | run_addons() { 67 | local OPT=`getopt -o mpi -- "$@"` NAME PNAME 68 | eval set -- "$OPT" 69 | while true; do 70 | case "$1" in 71 | -m) NAME=main; shift;; 72 | -p) NAME=preinstall; PNAME="Preinstall"; shift;; 73 | -i) NAME=install; PNAME="Install"; shift;; 74 | --) shift; break;; 75 | esac 76 | done 77 | if [ "$(ls -A $MODPATH/common/addon/*/$NAME.sh 2>/dev/null)" ]; then 78 | [ -z $PNAME ] || { ui_print " "; ui_print "- Running $PNAME Addons -"; } 79 | for i in $MODPATH/common/addon/*/$NAME.sh; do 80 | ui_print " Running $(echo $i | sed -r "s|$MODPATH/common/addon/(.*)/$NAME.sh|\1|")..." 81 | . $i 82 | done 83 | [ -z $PNAME ] || { ui_print " "; ui_print "- `echo $PNAME`ing (cont) -"; } 84 | fi 85 | } 86 | 87 | cp_ch() { 88 | local OPT=`getopt -o inr -- "$@"` BAK=true UBAK=true FOL=false 89 | eval set -- "$OPT" 90 | while true; do 91 | case "$1" in 92 | -n) UBAK=false; shift;; 93 | -r) FOL=true; shift;; 94 | --) shift; break;; 95 | *) abort "Invalid cp_ch argument $1! Aborting!";; 96 | esac 97 | done 98 | local SRC="$1" DEST="$2" OFILES="$1" 99 | $FOL && local OFILES=$(find $SRC -type f 2>/dev/null) 100 | [ -z $3 ] && PERM=0644 || PERM=$3 101 | case "$DEST" in 102 | $TMPDIR/*|$MODULEROOT/*|$NVBASE/modules/$MODID/*) BAK=false;; 103 | esac 104 | for OFILE in ${OFILES}; do 105 | if $FOL; then 106 | if [ "$(basename $SRC)" == "$(basename $DEST)" ]; then 107 | local FILE=$(echo $OFILE | sed "s|$SRC|$DEST|") 108 | else 109 | local FILE=$(echo $OFILE | sed "s|$SRC|$DEST/$(basename $SRC)|") 110 | fi 111 | else 112 | [ -d "$DEST" ] && local FILE="$DEST/$(basename $SRC)" || local FILE="$DEST" 113 | fi 114 | if $BAK && $UBAK; then 115 | [ ! "$(grep "$FILE$" $INFO 2>/dev/null)" ] && echo "$FILE" >> $INFO 116 | [ -f "$FILE" -a ! -f "$FILE~" ] && { mv -f $FILE $FILE~; echo "$FILE~" >> $INFO; } 117 | elif $BAK; then 118 | [ ! "$(grep "$FILE$" $INFO 2>/dev/null)" ] && echo "$FILE" >> $INFO 119 | fi 120 | install -D -m $PERM "$OFILE" "$FILE" 121 | done 122 | } 123 | 124 | install_script() { 125 | case "$1" in 126 | -l) shift; local INPATH=$NVBASE/service.d;; 127 | -p) shift; local INPATH=$NVBASE/post-fs-data.d;; 128 | *) local INPATH=$NVBASE/service.d;; 129 | esac 130 | [ "$(grep "#!/system/bin/sh" $1)" ] || sed -i "1i #!/system/bin/sh" $1 131 | local i; for i in "MODPATH" "LIBDIR" "MODID" "INFO" "MODDIR"; do 132 | case $i in 133 | "MODPATH") sed -i "1a $i=$NVBASE/modules/$MODID" $1;; 134 | "MODDIR") sed -i "1a $i=\${0%/*}" $1;; 135 | *) sed -i "1a $i=$(eval echo \$$i)" $1;; 136 | esac 137 | done 138 | [ "$1" == "$MODPATH/uninstall.sh" ] && return 0 139 | case $(basename $1) in 140 | post-fs-data.sh|service.sh) ;; 141 | *) cp_ch -n $1 $INPATH/$(basename $1) 0755;; 142 | esac 143 | } 144 | 145 | prop_process() { 146 | sed -i -e "/^#/d" -e "/^ *$/d" $1 147 | [ -f $MODPATH/system.prop ] || mktouch $MODPATH/system.prop 148 | while read LINE; do 149 | echo "$LINE" >> $MODPATH/system.prop 150 | done < $1 151 | } 152 | 153 | # Check for min/max api version 154 | [ -z $MINAPI ] || { [ $API -lt $MINAPI ] && abort "! Your system API of $API is less than the minimum api of $MINAPI! Aborting!"; } 155 | [ -z $MAXAPI ] || { [ $API -gt $MAXAPI ] && abort "! Your system API of $API is greater than the maximum api of $MAXAPI! Aborting!"; } 156 | 157 | # Set variables 158 | [ $API -lt 26 ] && DYNLIB=false 159 | [ -z $DYNLIB ] && DYNLIB=false 160 | [ -z $DEBUG ] && DEBUG=false 161 | [ -e "$PERSISTDIR" ] && PERSISTMOD=$PERSISTDIR/magisk/$MODID 162 | INFO=$NVBASE/modules/.$MODID-files 163 | ORIGDIR="$MAGISKTMP/mirror" 164 | if $DYNLIB; then 165 | LIBPATCH="\/vendor" 166 | LIBDIR=/system/vendor 167 | else 168 | LIBPATCH="\/system" 169 | LIBDIR=/system 170 | fi 171 | if ! $BOOTMODE; then 172 | ui_print "- Only uninstall is supported in recovery" 173 | ui_print " Uninstalling!" 174 | touch $MODPATH/remove 175 | [ -s $INFO ] && install_script $MODPATH/uninstall.sh || rm -f $INFO $MODPATH/uninstall.sh 176 | recovery_cleanup 177 | cleanup 178 | rm -rf $NVBASE/modules_update/$MODID $TMPDIR 2>/dev/null 179 | exit 0 180 | fi 181 | 182 | # Debug 183 | if $DEBUG; then 184 | ui_print "- Debug mode" 185 | LOGFILE=/storage/emulated/0/Download/$MODID-debug 186 | ui_print " Debug log will be written to: $LOGFILE.log" 187 | exec 2>$LOGFILE.log 188 | set -x 189 | fi 190 | 191 | # Extract files 192 | ui_print "- Extracting module files" 193 | unzip -o "$ZIPFILE" -x 'META-INF/*' 'common/functions.sh' -d $MODPATH >&2 194 | [ -f "$MODPATH/common/addon.tar.xz" ] && tar -xf $MODPATH/common/addon.tar.xz -C $MODPATH/common 2>/dev/null 195 | 196 | # Main addons 197 | run_addons -m 198 | 199 | # Remove files outside of module directory 200 | ui_print "- Removing old files" 201 | 202 | if [ -f $INFO ]; then 203 | while read LINE; do 204 | if [ "$(echo -n $LINE | tail -c 1)" == "~" ]; then 205 | continue 206 | elif [ -f "$LINE~" ]; then 207 | mv -f $LINE~ $LINE 208 | else 209 | rm -f $LINE 210 | while true; do 211 | LINE=$(dirname $LINE) 212 | [ "$(ls -A $LINE 2>/dev/null)" ] && break 1 || rm -rf $LINE 213 | done 214 | fi 215 | done < $INFO 216 | rm -f $INFO 217 | fi 218 | 219 | ### Install 220 | ui_print "- Installing" 221 | 222 | run_addons -p 223 | [ -f "$MODPATH/common/install.sh" ] && . $MODPATH/common/install.sh 224 | run_addons -i 225 | 226 | ui_print " Installing for $ARCH SDK $API device..." 227 | # Remove comments from files and place them, add blank line to end if not already present 228 | for i in $(find $MODPATH -type f -name "*.sh" -o -name "*.prop" -o -name "*.rule"); do 229 | [ -f $i ] && { sed -i -e "/^#/d" -e "/^ *$/d" $i; [ "$(tail -1 $i)" ] && echo "" >> $i; } || continue 230 | case $i in 231 | "$MODPATH/service.sh") install_script -l $i;; 232 | "$MODPATH/post-fs-data.sh") install_script -p $i;; 233 | "$MODPATH/uninstall.sh") [ -s $INFO ] && install_script $MODPATH/uninstall.sh || rm -f $INFO $MODPATH/uninstall.sh;; 234 | esac 235 | done 236 | 237 | $IS64BIT || for i in $(find $MODPATH/system -type d -name "lib64"); do rm -rf $i 2>/dev/null; done 238 | [ -d "/system/priv-app" ] || mv -f $MODPATH/system/priv-app $MODPATH/system/app 2>/dev/null 239 | [ -d "/system/xbin" ] || mv -f $MODPATH/system/xbin $MODPATH/system/bin 2>/dev/null 240 | if $DYNLIB; then 241 | for FILE in $(find $MODPATH/system/lib* -type f 2>/dev/null | sed "s|$MODPATH/system/||"); do 242 | [ -s $MODPATH/system/$FILE ] || continue 243 | case $FILE in 244 | lib*/modules/*) continue;; 245 | esac 246 | mkdir -p $(dirname $MODPATH/system/vendor/$FILE) 247 | mv -f $MODPATH/system/$FILE $MODPATH/system/vendor/$FILE 248 | [ "$(ls -A `dirname $MODPATH/system/$FILE`)" ] || rm -rf `dirname $MODPATH/system/$FILE` 249 | done 250 | # Delete empty lib folders (busybox find doesn't have this capability) 251 | toybox find $MODPATH/system/lib* -type d -empty -delete >/dev/null 2>&1 252 | fi 253 | 254 | # Set permissions 255 | ui_print " " 256 | ui_print "- Setting Permissions" 257 | set_perm_recursive $MODPATH 0 0 0755 0644 258 | if [ -d $MODPATH/system/vendor ]; then 259 | set_perm_recursive $MODPATH/system/vendor 0 0 0755 0644 u:object_r:vendor_file:s0 260 | [ -d $MODPATH/system/vendor/app ] && set_perm_recursive $MODPATH/system/vendor/app 0 0 0755 0644 u:object_r:vendor_app_file:s0 261 | [ -d $MODPATH/system/vendor/etc ] && set_perm_recursive $MODPATH/system/vendor/etc 0 0 0755 0644 u:object_r:vendor_configs_file:s0 262 | [ -d $MODPATH/system/vendor/overlay ] && set_perm_recursive $MODPATH/system/vendor/overlay 0 0 0755 0644 u:object_r:vendor_overlay_file:s0 263 | for FILE in $(find $MODPATH/system/vendor -type f -name *".apk"); do 264 | [ -f $FILE ] && chcon u:object_r:vendor_app_file:s0 $FILE 265 | done 266 | fi 267 | set_permissions 268 | 269 | # Complete install 270 | cleanup 271 | -------------------------------------------------------------------------------- /customize.sh: -------------------------------------------------------------------------------- 1 | ########################################################################################## 2 | # 3 | # MMT Extended Config Script 4 | # 5 | ########################################################################################## 6 | 7 | ########################################################################################## 8 | # Config Flags 9 | ########################################################################################## 10 | 11 | # Uncomment and change 'MINAPI' and 'MAXAPI' to the minimum and maximum android version for your mod 12 | # Uncomment DYNLIB if you want libs installed to vendor for oreo+ and system for anything older 13 | # Uncomment DEBUG if you want full debug logs (saved to /sdcard) 14 | #MINAPI=21 15 | #MAXAPI=25 16 | #DYNLIB=true 17 | #DEBUG=true 18 | 19 | ########################################################################################## 20 | # Replace list 21 | ########################################################################################## 22 | 23 | # List all directories you want to directly replace in the system 24 | # Check the documentations for more info why you would need this 25 | 26 | # Construct your list in the following format 27 | # This is an example 28 | REPLACE_EXAMPLE=" 29 | /system/app/Youtube 30 | /system/priv-app/SystemUI 31 | /system/priv-app/Settings 32 | /system/framework 33 | " 34 | 35 | # Construct your own list here 36 | REPLACE=" 37 | " 38 | 39 | ########################################################################################## 40 | # Permissions 41 | ########################################################################################## 42 | 43 | set_permissions() { 44 | : # Remove this if adding to this function 45 | 46 | # Note that all files/folders in magisk module directory have the $MODPATH prefix - keep this prefix on all of your files/folders 47 | # Some examples: 48 | 49 | # For directories (includes files in them): 50 | # set_perm_recursive (default: u:object_r:system_file:s0) 51 | 52 | # set_perm_recursive $MODPATH/system/lib 0 0 0755 0644 53 | # set_perm_recursive $MODPATH/system/vendor/lib/soundfx 0 0 0755 0644 54 | 55 | # For files (not in directories taken care of above) 56 | # set_perm (default: u:object_r:system_file:s0) 57 | 58 | # set_perm $MODPATH/system/lib/libart.so 0 0 0644 59 | # set_perm /data/local/tmp/file.txt 0 0 644 60 | } 61 | 62 | ########################################################################################## 63 | # MMT Extended Logic - Don't modify anything after this 64 | ########################################################################################## 65 | 66 | SKIPUNZIP=1 67 | unzip -qjo "$ZIPFILE" 'common/functions.sh' -d $TMPDIR >&2 68 | . $TMPDIR/functions.sh 69 | -------------------------------------------------------------------------------- /module.prop: -------------------------------------------------------------------------------- 1 | id=a12_volume_adjustment 2 | name=Android 12 Volume Adjustment for Remote Group Sessions 3 | version=v1.0 4 | versionCode=1 5 | author=MishaalRahman 6 | description=Re-enable volume adjustment for group cast sessions -------------------------------------------------------------------------------- /system/product/overlay/A12_VolumeAdjustmentOverlay/A12VolumeAdjustmentOverlay.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MishaalRahmanGH/Android-12-Speaker-Group-Volume-Adjustment-Fix/bf8685d7c87081af755b5dde4a1253198fc4fa0b/system/product/overlay/A12_VolumeAdjustmentOverlay/A12VolumeAdjustmentOverlay.apk -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | # Don't modify anything after this 2 | if [ -f $INFO ]; then 3 | while read LINE; do 4 | if [ "$(echo -n $LINE | tail -c 1)" == "~" ]; then 5 | continue 6 | elif [ -f "$LINE~" ]; then 7 | mv -f $LINE~ $LINE 8 | else 9 | rm -f $LINE 10 | while true; do 11 | LINE=$(dirname $LINE) 12 | [ "$(ls -A $LINE 2>/dev/null)" ] && break 1 || rm -rf $LINE 13 | done 14 | fi 15 | done < $INFO 16 | rm -f $INFO 17 | fi 18 | --------------------------------------------------------------------------------