使用mapfile将输出保存到关联数组

时间:2016-10-26 17:50:39

标签: arrays bash associative-array

在练习bash时,我尝试编写一个脚本,在主目录中搜索主目录中的重复文件并删除它们。这是我的脚本现在的样子。

#!/bin/bash

# create-list: create a list of regular files in a directory

declare -A arr1 sumray origray

if [[ -d "$HOME/$1" && -n "$1" ]]; then
    echo "$1 is a directory"
else
    echo "Usage: create-list Directory | options" >&2
    exit 1
fi

for i in $HOME/$1/*; do
    [[ -f $i ]] || continue
    arr1[$i]="$i"
done

for i in "${arr1[@]}"; do
    Name=$(sed 's/[][?*]/\\&/g' <<< "$i")
    dupe=$(find ~ -name "${Name##*/}" ! -wholename "$Name")

    if [[ $(find ~ -name "${Name##*/}" ! -wholename "$Name") ]]; then
        mapfile -t sumray["$i"] < <(find ~ -name "${Name##*/}" ! -wholename "$Name")
        origray[$i]=$(md5sum "$i" | cut -c 1-32)
    fi
done

for i in "${!sumray[@]}"; do
    poten=$(md5sum "$i" | cut -c 1-32)
    for i in "${!origray[@]}"; do
        if [[ "$poten" = "${origray[$i]}" ]]; then
            echo "${sumray[$i]} is a duplicate of $i"
        fi
    done
done

最初,mapfile -t sumray["$i"] < <(find ~ -name "${Name##*/}" ! -wholename "$Name")现在在哪里,我的行如下:

sumray["$i"]=$(find ~ -name "${Name##*/}" ! -wholename "$Name")

这将find的输出保存到数组中。但我有一个问题。如果单个文件有多个重复项,则find找到的所有位置都将保存为单个值。我想我可以使用mapfile命令来解决这个问题,但现在它根本没有保存到我的数组中。这是否与我使用关联数组的事实有关?或者我在其他地方搞砸了?

1 个答案:

答案 0 :(得分:1)

我不确定我是否可以回答我自己的问题,但我认为我应该发布解决问题的方法。

事实证明,mapfile命令根本不适用于关联数组。所以我的修复是将find的输出保存到文本文件,然后将该信息存储在索引数组中。我测试了几次,但我似乎还没有遇到任何错误。

这是我完成的剧本。

#!/bin/bash

# create-list: create a list of regular files in a directory

declare -A arr1 origray
declare indexray

#Verify that Parameter is a directory.
if [[ -d "$HOME/$1/" && -n "$1" ]]; then
    echo "Searching for duplicates of files in $1"
else
    echo "Usage: create-list Directory | options" >&2
    exit 1
fi

#create list of files in specified directory
for i in $HOME/${1%/}/*; do
    [[ -f $i ]] || continue
    arr1[$i]="$i"
done

#search for all duplicate files in the home directory
#by name
#find checksum of files in specified directory
for i in "${arr1[@]}"; do
    Name=$(sed 's/[][?*]/\\&/g' <<< "$i")

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

#create list of duplicate file locations.
if [[ -f temp.txt ]]; then
    mapfile -t indexray < temp.txt
else
    echo "No duplicates were found."
    exit 0
fi

#compare similarly named files by checksum and delete duplicates
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 $1."
        fi
    done
    count=$((count+1))
done

rm temp.txt

这有点草率,但它做了它应该做的事情。 md5sum可能不是检查文件重复的最佳方法,但它可以工作。我所要做的就是将echo "${indexray[$count]} is a duplicate of a file in $1."替换为rm -i ${indexray[$count]},这样做很不错。

所以我的下一个问题必须是......为什么mapfile不能与关联数组一起工作?