我正在尝试制作一个执行以下操作的bash脚本:
问题是删除包含先前存储的文件路径/校验和的行的sed命令在for循环中不起作用。但是,如果我将单个文件作为参数传递而不是创建文件数组并循环遍历,则相同的算法也可以工作。
下面的代码示例:
#! /bin/bash
file_array=$(find sdcard -type f)
for path in ${file_array[@]}
do
hash=$(shasum $path | cut -f 1 -d " ")
# Search through the file that stores hashed files (path and chksum)
file_count=$(grep -c -w $path droidhash.csv)
echo "filecount: $file_count"
#If the file is found, preform commands based on this
if [ $file_count -ge 1 ]
then
echo "File found, replacing line"
sed -i "/"$path"/d" droidhash.csv
echo $path';'$hash | cat >> droidhash.csv
else
echo "File not found, adding line"
echo $path';'$hash | cat >> droidhash.csv
fi
done
运行脚本时收到的错误消息是:
“sed:-e表达式#1,字符9:未知命令:`f'”
是否可以在for循环中使用此sed命令?
答案 0 :(得分:2)
要实际创建数组,需要额外的括号:
file_array=( $(find sdcard -type f) )
然后,引用数组扩展
非常重要for path in "${file_array[@]}"
然后在您使用它的任何地方引用路径变量
hash=$(shasum "$path" | cut -f 1 -d " ")
请参阅Security implications of forgetting to quote a variable in bash/POSIX shells
由于您正在寻找固定字符串,请告诉grep:
file_count=$(grep -F -c -w "$path" droidhash.csv)
然后按照@ JH的建议:" $ path"包含斜杠字符,因此您需要在sed的s///
命令中使用不同的分隔符。
第二个想法,我会像这样重写:
find sdcard -type f -print0 | while IFS= read -d "" -r path; do
hash=$(shasum "$path" | cut -f 1 -d " ")
if grep -q "^$path;" droidhash.csv; then
echo "File $path found, replacing line"
gawk -i inplace '$1 == p {$2 = h}; 1' FS=";" OFS=";" p="$path" h="$hash" droidhash.csv
else
echo "File $path not found, adding line"
echo "$path;$hash" >> droidhash.csv
fi
done
答案 1 :(得分:1)
sed -i "/"$path"/d" droidhash.csv
你的报价很奇怪。您可能对sed -i ";${path};d" droidhash.csv
感到满意。
而不是else
条款,只是无条件地附加到CSV。如果不使用cat
,echo
也可以追加。{/ p>