2016-11-29 2 views
-1

В конечном счете, я хочу избавиться от возможности дублирования записей, отображающих мой массив. Причина, по которой я это делаю, заключается в том, что я работаю над скриптом, который сравнивает два каталога, ищет и удаляет дубликаты файлов. Потенциальные дубликаты файлов хранятся в массиве, и файлы удаляются только в том случае, если они имеют одинаковое имя и контрольную сумму в качестве оригиналов. Поэтому, если есть повторяющиеся записи, я сталкиваюсь с небольшими ошибками, когда md5 либо пытается найти контрольную сумму файла, который не существует (поскольку он уже был удален), либо rm пытается удалить уже удаленный файл.Как отсортировать содержимое массивов?

Вот часть сценария.

compare() 
{ 

read -p "Please enter two directories: " dir1 dir2 

if [[ -d "$dir1" && -d "$dir2" ]]; then 
    echo "Searching through $dir2 for duplicates of files in $dir1..." 
else 
    echo "Invalid entry. Please enter valid directories." >&2 
    exit 1 
fi 

#create list of files in specified directory 
while read -d $'\0' file; do 
    test_arr+=("$file") 
done < <(find $dir1 -print0) 

#search for all duplicate files in the home directory 
#by name 
#find checksum of files in specified directory 
tmpfile=$(mktemp -p $dir1 del_logXXXXX.txt) 


for i in "${test_arr[@]}"; do 
    Name=$(sed 's/[][?*]/\\&/g' <<< "$i") 

    if [[ $(find $dir2 -name "${Name##*/}" ! -wholename "$Name") ]]; then 
     [[ -f $i ]] || continue 
     find $dir2 -name "${Name##*/}" ! -wholename "$Name" >> $tmpfile 
     origray[$i]=$(md5sum "$i" | cut -c 1-32) 
    fi 
done 

#create list of duplicate file locations. 
dupe_loc 

#compare similarly named files by checksum and delete duplicates 
local count=0 
for i in "${!indexray[@]}"; do 
    poten=$(md5sum "${indexray[$i]}" | cut -c 1-32) 
    for i in "${!origray[@]}"; do 
     if [[ "$poten" = "${origray[$i]}" ]]; then 
      echo "${indexray[$count]} is a duplicate of a file in $dir1." 
      rm -v "${indexray[$count]}" 
      break 
     fi 
    done 
    count=$((count+1)) 
done 
exit 0 
} 

dupe_loc - следующая функция.

dupe_loc() 
{ 
if [[ -s $tmpfile ]]; then 
    mapfile -t indexray < $tmpfile 
else 
    echo "No duplicates were found." 
    exit 0 
fi 
} 

Я полагаю, что лучший способ решить эту проблему было бы использовать команды sort и uniq распоряжаться повторяющихся записей в массиве. Но даже при замене процесса я сталкиваюсь с ошибками при попытке сделать это.

+1

Можете ли вы упростить эту проблему дальше? Скажем, у вас есть 2 каталога с файлами, и вы хотите иметь 3-й каталог с единственным уникальным контентом из обоих каталогов? – NinjaGaiden

+1

'sort -u -kN, M' должно быть достаточно. Слишком много кода для этой проблемы, пожалуйста, прочитайте http://stackoverflow.com/help/mcve, прежде чем отправлять больше вопросов здесь. Удачи. – shellter

+0

Более простым подходом было бы заполнить 'test_arr' именем файла (без пути), и как только вы заполняете' test_arr', просто нужно прокрутить имена и 'test', если есть файл в каталоге dir2 с этим именем, например. 'test_arr + = (" $ {file ## * /} ")', затем 'declare -a dups; для i в "$ {test_arr [@]}"; do [-f "$ dir2/$ i"] && dups + = ("$ i"); done' Теперь у вас есть список дубликатов в 'dups'. –

ответ

0

Прежде всего. На выбор массива Bash ответил: How to sort an array in BASH

Это не означает, что сортировка массива будет очень полезной. Похоже, что более простое решение будет просто обернуть ваши проверки md5 и rm в заявлении if:

if [ -f origarr[$i]} ]; do #True if file exists and is a regular file. 
    #file exists 
    ... 
    rm ${origarr[$i]} 
fi 
Смежные вопросы