#!/bin/bash # This script leaves one of duplicated files unchanged and changes the other duplicated files to symbolic links to the left file. # The modified time of the generated symbolic link is adjusted to the round-up minutes of the modified time of its original file (not the left file). # The name of the generated symbolic link is that of its originial file (not the left file). # Written by Kiyoshi SUZUKI ("kiyop" in Debian forum and Ubuntu forum and Ubuntu Japanese Team Forum) # Many "echo ... " are intended to do bug fix. scroll () { a=0 while [ $a -lt $1 ];do echo a=$(expr $a + 1) done } width=$(dialog --print-maxsize 2>&1|head -n1|cut -d " " -f3) height=$(dialog --print-maxsize 2>&1|head -n1|cut -d " " -f2|tr -d ,) # echo $width $height if [ -e fdupes2.log ];then dialog --msgbox "This script will delete fdupes2.log. Please use this script on the directory which does not contain fdupes2.log" $height $width exit 1 fi if [ -e fdupes2.log2 ];then dialog --msgbox "This script will delete fdupes2.log. Please use this script on the directory which does not contain fdupes2.log2" $height $width exit 1 fi if [ -n "$(pwd|grep ' ')" ];then dialog --msgbox "This script cannot work correctly on a directory the name of which involves space." $height $width exit 1 fi makelink () { savedir=$(echo $2|sed -e "s/[^\/]*$//") # echo "savedir=" $savedir if [ "$(echo "$savedir"|cut -c1)" != "/" ] then savedir="${PWD}/${savedir}" # echo "savedir=" $savedir fi if [ -n "$(echo "$savedir"|tr "/" '\n'|tail -n1)" ] then savedir="${savedir}/" # echo "savedir=" $savedir fi while [ "$(echo "$savedir"|grep -G "\/\.\/")" ];do savedir="$(echo "$savedir"|sed -e "s/\/\.\//\//g")" # echo "savedir=" $savedir done while [ "$(echo "$savedir"|grep -G "\/[^\/]*[^\/\.]\+[^\/]*\/\.\.\/\|\/\.\{3,\}\/\.\.\/")" ];do savedir="$(echo "$savedir"|sed -e "s@/[^/]*[^/\.]\+[^/]*/\.\./\|/\.\{3,\}/\.\./@/@g")" # echo "savedir=" $savedir done # The first letter of $savedir is /, and the last letter is /. There is no "/./" nor "/../" in $savedir. savedir1="$(echo "$savedir"|sed -e "s@\([^/]*/\)@\1\n@"|head -n1)" savedir2="$(echo "$savedir"|sed -e "s@\([^/]*/\)@\1\n@"|tail -n1)" # $savedir1 is /, the first letter of $savedir2 is not /. The last letter of $savedir is /. There is no "/./" nor "/../" in $savedir2. while [ -n "$savedir2" ];do if [ "$(echo "$savedir1"|cut -c1)" != "/" ] then savedir1="${PWD}/${savedir1}" fi cd "$savedir1" savedir3="$(echo "$savedir2"|sed -e "s/\([^\/]*\)\//\1\n/"|head -n1)" # echo $savedir1 , $savedir2 , $savedir3 if [ "$(ls -l "$savedir3"|cut -c1)" = "l" ] then # $savedir3, whose last letter is not /, is symbolic link. savedir4="$(ls -l "$savedir3"|sed -e "s/ -> /\n/g"|tail -n1)" if [ "$(echo "$savedir4"|cut -c1)" = "/" ] then # The first letter of $savedir4(the destination directory of the symbolic link)is / savedir="$(echo ${savedir4}|sed -e "s/\/$//")/$(echo "$savedir2"|sed -e "s/[^\/]*\///")" else # The first letter of $savedir4(the destination directory of the symbolic link)is not / savedir="${savedir1}$(echo ${savedir4}|sed -e "s/\/$//")/$(echo "$savedir2"|sed -e "s/[^\/]*\///")" fi if [ -n "$(echo "$savedir"|tr "/" '\n'|tail -n1)" ];then savedir="${savedir}/" fi while [ "$(echo "$savedir"|grep -G "\/\.\/")" ];do savedir="$(echo "$savedir"|sed -e "s/\/\.\//\//g")" done while [ "$(echo "$savedir"|grep -G "\/[^\/]*[^\/\.]\+[^\/]*\/\.\.\/\|\/\.\{3,\}\/\.\.\/")" ];do savedir="$(echo "$savedir"|sed -e "s/\/[^\/]*[^\/\.]\+[^\/]*\/\.\.\/\|\/\.\{3,\}\/\.\.\//\//g")" done # The first letter of $savedir is /, and there is no "/./" nor "/../" in $savedir savedir1="$(echo "$savedir"|sed -e "s/\([^\/]*\/\)/\1\n/"|head -n1)" savedir2="$(echo "$savedir"|sed -e "s/\([^\/]*\/\)/\1\n/"|tail -n1)" else # $savedir3 is not a symbolic link. savedir1="${savedir1}${savedir3}/" savedir2="$(echo "${savedir2}"|sed -e "s/[^\/]*\///")" fi done savedir="$(echo ${savedir1}|sed -e "s/\/$//")" # The first letter of $savedir is /, the last letter fo $savedir is not /, and there is no "/./" nor "/../" in $savedir cd $savedir savedir1=$savedir savedir1=$(echo $savedir1|cut -c2-) link=$(echo "$currentdir/$1"|cut -c2-) # echo "originalfile is " $link until [ a$(echo $link|grep \/) = "a" -o a${savedir1} = "a" ];do if [ a$(echo $link|sed -e "s/\//\n/g"|head -n 1) = a$(echo $savedir1|sed -e "s/\//\n/g"|head -n 1) ];then num=$(expr $(echo $link|sed -e "s/\//\n/g"|head -n 1|wc -c) + 1) link=$(echo $link|cut -c${num}-) savedir1=$(echo $savedir1|cut -c${num}-) else break fi done if [ a$savedir1 = "a" ];then num=0 else num=$(echo $savedir1|sed -e "s/\//\n/g"|wc -l) fi while [ $num -gt 0 ];do link="../"${link} num=$(expr $num - 1) done echo "link is tried to be made for $link with the name $(basename $2) in $PWD" >> $logfilename ln -s "${link}" $(basename $2) if [ $? = 1 ];then dialog --title "" --msgbox "${savedir}/${linkname} cannot be made.\nMaybe there is not write permission of ${savedir}.\nPlease select a directory with write permission.\nThe link is not generated." $height $width echo "${savedir}/${linkname} cannot be made.\nMaybe there is not write permission of ${savedir}.\nPlease select a directory with write permission.\nThe link is not generated." >> $logfilename # Return to original directory after the above task finished. cd $currentdir exit 1 else echo "The above is succeeded." >> $logfilename fi cd $currentdir } currentdir=$PWD # echo "currentdir=" $currentdir logbegindate="$(date +%C%y%m%d%k%M|tr -d ' ')" logfilename="$currentdir/fdupes.log_$logbegindate" touch $logfilename # echo $logfilename fdupes -rn . > fdupes2.log2 echo "The below is the result of \"fdupes -rn .\" at $(pwd) at $logbegindate =====" >> $logfilename cat fdupes2.log2 >> $logfilename sed -e "s@^./@@" fdupes2.log2 > fdupes2.log rm fdupes2.log2 logfilename="$currentdir/fdupes2.log_$logbegindate" touch $logfilename # echo $logfilename echo "The below is the log of fdupes2 at $(pwd) at $logbegindate =====" >> $logfilename while [ $(wc -l fdupes2.log|cut -d " " -f1) -gt 1 ];do dealtlines="$(sed -e "/^$/q" fdupes2.log|grep -v ^$)" # echo "dealt lines are" $dealtlines if [ -z "$dealtlines" ];then # echo "there is no line" mv fdupes2.log fdupes2.log2 sed -e "1d" fdupes2.log2 > fdupes2.log rm fdupes2.log2 continue fi echo "" >> $logfilename if [ -n "$(echo "$dealtlines"|grep ' ')" ];then dialog --msgbox "This script cannot deal files with full path involving ' '. Skip $dealtlines" $height $width echo "This script cannot deal files with full path involving ' '. The following files are skipped. $dealtlines" >> $logfilename mv fdupes2.log fdupes2.log2 num=$(echo "$dealtlines"|wc -l|cut -d " " -f1) num=$(expr $num + 1) sed -e 1,${num}d fdupes2.log2 > fdupes2.log rm fdupes2.log2 continue fi strings=$(echo "$dealtlines"|sed -n -e = -e p) # echo "selected menu to be shown is" $strings # scroll $height selected=$(dialog --no-shadow --colors --stdout --menu "Select the file to keep. The others will be changed to symbolic links" $height $width 10 $strings) if [ $? = 1 ];then echo "The following files are skipped according to the request. $dealtlines" >> $logfilename mv fdupes2.log fdupes2.log2 num=$(echo "$dealtlines"|wc -l|cut -d " " -f1) num=$(expr $num + 1) sed -e 1,${num}d fdupes2.log2 > fdupes2.log rm fdupes2.log2 continue fi # echo "selected number is " $selected originalfile=$(echo "$dealtlines"|sed -n -e ${selected}p) # echo "original file to be kept is" $originalfile dealtlines=$(echo "$dealtlines"|grep -v ^$originalfile\$) # echo "files to be changed to symbolic links are" $dealtlines for dealt in $dealtlines;do time=$(ls --full-time $dealt|cut -d " " -f 6-7|tr -d " "|tr -d :|tr -d -|sed -e "s/\..*//") # echo "time is $time" time=$(echo $time|cut -c 1-12) # echo "time is $time" filedata=$(ls -l $dealt) rm $dealt if [ $? = 1 ];then dialog --title "" --msgbox "$dealt cannot be deleted.\nMaybe we do not have write permission of it.\nPlease select a directory with write permission.\nThe link is not generated." $height $width echo "$dealt cannot be deleted.\nMaybe we do not have write permission of it.\nPlease select a directory with write permission.\nThe link is not generated. --" >> $logfilename continue else echo "The following file is deleted. $filedata" >> $logfilename fi makelink "$originalfile" "$dealt" touch -c -h -t ${time}.60 $dealt if [ $? = 1 ];then echo "The modified time of $dealt is failed to be changed." >> $logfilename else echo "The modified time of $dealt is successfully changed to ${time}.60" >> $logfilename fi # The minutes is round up so that the original file is overwritten by the generated symbolic link if "cp -au" is used to synchronize. echo "--" >> $logfilename done mv fdupes2.log fdupes2.log2 num=$(echo "$dealtlines"|wc -l|cut -d " " -f1) num=$(expr $num + 1) sed -e 1,${num}d fdupes2.log2 > fdupes2.log rm fdupes2.log2 done rm fdupes2.log exit 0