我需要编写一个bash脚本来迭代指定目录的文件,并用硬链接替换文件的副本。现在,我的整个函数看起来像这样:
#! /bin/bash
# sameln --- remove duplicate copies of files in specified directory
D=$1
cd $D #go to directory specified as default input
fileNum=0 #loop counter
DIR=".*|*"
for f in $DIR #for every file in the directory
do
files[$fileNum]=$f #save that file into the array
fileNum=$((fileNum+1)) #increment the counter
done
for((j=0; j<$fileNum; j++)) #for every file
do
if [ -f "$files[$j]" ] #access that file in the array
then
for((k=0; k<$fileNum; k++)) #for every other file
do
if [ -f "$files[$k]" ] #access other files in the array
then
test[cmp -s ${files[$j]} ${files[$k]}] #compare if the files are identical
[ln ${files[$j]} ${files[$k]}] #change second file to a hard link
fi
done
fi
done
基本上:
测试目录有四个文件:a,b,c,d
a和b不同,但c和d是重复的(它们是空的)。运行脚本后,ls -l显示所有文件仍然只有1个硬链接,因此脚本似乎基本上什么也没做。
我哪里错了?
答案 0 :(得分:1)
DIR=".*|*"
for f in $DIR #for every file in the directory
do
echo $f
done
此代码输出
.*|*
你不应该循环这样的文件。查看find
命令。如您所见,您的代码无法正常工作,因为第一个循环已经出现故障。
顺便说一句,不要将变量全部大写,我相信这些变量都是为系统变量保留的。
答案 1 :(得分:1)
你可能会让自己的这个过程比必要时更难。已经有一个Linux命令fdupes
扫描一个逐字节的目录,md5sum,date&amp;时间比较,以确定文件是否是彼此的重复。它可以轻松查找和返回重复文件组。只剩下使用结果了。
以下是使用此工具进行工作的快速示例。 注意此快速示例仅适用于不包含空格的文件名。如果要处理包含空格的文件名,则必须对其进行修改。这是为了展示使用已经完成您想要的工具的方法。另外注意实际的ln
命令在下面被注释掉了。该程序只是打印它会做什么。测试完成后,您可以在对结果满意后删除对ln
命令的注释。
#! /bin/bash
# sameln --- remove duplicate copies of files in specified directory using fdupes
[ -d "$1" ] || { # test valid directory supplied
printf "error: invalid directory '%s'. usage: %s <dir>\n" "$1" "${0//\//}"
exit 1
}
type fdupes &>/dev/null || { # verify fdupes is available in path
printf "error: 'fdupes' required. Program not found within your path\n"
exit 1
}
pushd "$1" &>/dev/null # go to directory specified as default input
declare -a files # declare files and dupes array
declare -a dupes
## read duplicate files into files array
IFS=$'\n' read -d '' -a files < <(fdupes --sameline .)
## for each list of duplicates
for ((i = 0; i < ${#files[@]}; i++)); do
printf "\n duplicate files %s\n\n" "${files[i]}"
## split into original files (no interal 'spaces' allowed in filenames)
dupes=( ${files[i]} )
## for the 1st duplicate on
for ((j = 1; j < ${#dupes[@]}; j++)); do
## create hardlink to original (actual command commented)
printf " ln -f %s %s\n" "${dupes[0]}" "${dupes[j]}"
# ln -f "${dupes[0]}" "${dupes[j]}"
done
done
exit 0
<强>输出/实施例强>
$ bash rmdupes.sh dat
duplicate files ./output.dat ./tmptest ./env4.dat.out
ln -f ./output.dat ./tmptest
ln -f ./output.dat ./env4.dat.out
duplicate files ./vh.conf ./vhawk.conf
ln -f ./vh.conf ./vhawk.conf
duplicate files ./outfile.txt ./newfile.txt
ln -f ./outfile.txt ./newfile.txt
duplicate files ./z1 ./z1cpy
ln -f ./z1 ./z1cpy