2016-10-26 11 views
0

bashの練習では、ホームディレクトリ内の重複したファイルをホームディレクトリで検索して削除するスクリプトを作成しようとしました。ここに私のスクリプトがどのように見えるかがあります。このアレイに見つけるの出力を保存しmapfileを使って出力を連想配列に保存する

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

mapfile -t sumray["$i"] < <(find ~ -name "${Name##*/}" ! -wholename "$Name")は今どこ

#!/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 

はもともと、私のラインは以下の通りでした。しかし、私には問題がありました。 1つのファイルに複数の重複がある場合、findによって検出されたすべての場所は単一の値に保存されます。私はmapfileコマンドを使ってこれを修正できると考えましたが、現在は配列に何も保存していません。私は連想配列を使っているという事実と関係がありますか?それとも、私は他の場所でちょうどうんざりしましたか?

答えて

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]}と置き換えればいいです。

私の次の質問は...なぜマップファイルが連想配列で動作しないのでしょうか?

+0

bashでは、配列要素は配列(索引付けされているか結合されているかにかかわらず)にすることはできません。 – rici

+0

@rici mapfileは連想配列でも使えますか?私は配列要素がbashの配列ではないことを知っていますが、元の投稿がその配列をどのように引き起こしたかわかりません。 – Alphatron

+0

あなたは 'mapfile -t sumray [" $ i "]';を持っていました。私は、 '' sumray'の '$ i'要素に格納されている配列に行を読み込む以外に、解釈する方法はありませんが、連想配列の要素はスカラーでなければ動作できません。 (もしあなたの意図が 'sumray'をマルチマップにするのであれば、bashはマルチマップを持っていないので、これはうまくいっていません。) – rici

関連する問題