使用 mapfile 将输出保存到关联数组
Using mapfile to save output to associative arrays
在实践中bash,我尝试编写一个脚本,在主目录中搜索主目录中的重复文件并将其删除。这是我的脚本现在的样子。
#!/bin/bash
# create-list: create a list of regular files in a directory
declare -A arr1 sumray origray
if [[ -d "$HOME/" && -n "" ]]; then
echo " is a directory"
else
echo "Usage: create-list Directory | options" >&2
exit 1
fi
for i in $HOME//*; 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 找到的所有位置都将保存为一个值。我想我可以使用 mapfile 命令来解决这个问题,但现在它根本没有将任何内容保存到我的数组中。它与我使用关联数组的事实有关吗?还是我只是在其他地方搞砸了?
我不确定我是否可以回答我自己的问题,但我想我应该 post 我是如何解决我的问题的。
事实证明,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//" && -n "" ]]; then
echo "Searching for duplicates of files in "
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 ."
fi
done
count=$((count+1))
done
rm temp.txt
这有点草率,但它做了它应该做的事情。 md5sum 可能不是检查文件重复项的最佳方法,但它确实有效。我所要做的就是用 rm -i ${indexray[$count]}
替换 echo "${indexray[$count]} is a duplicate of a file in ."
就可以了。
所以我的下一个问题是...为什么 mapfile 不能与关联数组一起使用?
在实践中bash,我尝试编写一个脚本,在主目录中搜索主目录中的重复文件并将其删除。这是我的脚本现在的样子。
#!/bin/bash
# create-list: create a list of regular files in a directory
declare -A arr1 sumray origray
if [[ -d "$HOME/" && -n "" ]]; then
echo " is a directory"
else
echo "Usage: create-list Directory | options" >&2
exit 1
fi
for i in $HOME//*; 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 找到的所有位置都将保存为一个值。我想我可以使用 mapfile 命令来解决这个问题,但现在它根本没有将任何内容保存到我的数组中。它与我使用关联数组的事实有关吗?还是我只是在其他地方搞砸了?
我不确定我是否可以回答我自己的问题,但我想我应该 post 我是如何解决我的问题的。
事实证明,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//" && -n "" ]]; then
echo "Searching for duplicates of files in "
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 ."
fi
done
count=$((count+1))
done
rm temp.txt
这有点草率,但它做了它应该做的事情。 md5sum 可能不是检查文件重复项的最佳方法,但它确实有效。我所要做的就是用 rm -i ${indexray[$count]}
替换 echo "${indexray[$count]} is a duplicate of a file in ."
就可以了。
所以我的下一个问题是...为什么 mapfile 不能与关联数组一起使用?