2016-10-26 6 views
0

bash를 연습하면서 홈 디렉토리에서 중복 파일을 검색하고 삭제하는 스크립트를 작성했습니다. 여기 내 스크립트가 어떻게 생겼는지 알려줍니다. 이 배열에 찾을 수의 출력을 저장매핑 파일을 사용하여 연관 배열에 출력 저장

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 

원래, 내 라인은 다음이었다. 그러나 나는 문제가 있었다. 단일 파일에 여러 개의 중복이있는 경우 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]}으로 바꾸는 것뿐입니다.

그럼 내 다음 질문은 ... 왜 연관 배열과 mapfile이 작동하지 않을까요?

+0

bash에서 배열 요소는 배열이 될 수 없습니다 (배열의 색인 생성 또는 결합 여부). – rici

+0

@rici 따라서 맵 파일은 연관 배열에서 작동 할 수 있습니까? 나는 배열 요소가 bash에서 배열이 될 수 없다는 것을 알고 있지만, 원래의 게시물이 어떻게 그 배열을 생성했는지는 알지 못합니다. – Alphatron

+0

당신은'mapfile -t sumray [ "$ i"]'; "sumray"의 원소 '$ i'에 저장된 배열에 행을 읽어들이는 것 외에는 해석 할 방법이 없습니다. 그러나 연관 배열의 요소는 스칼라 여야하며 작동하지 않습니다. (만약 당신의 의도가'sumray'를 멀티 맵으로 만들려한다면, bash는 멀티 맵을 가지고 있지 않기 때문에 eithet은 작동하지 않을 것입니다.) – rici