for循环中sed命令的问题

时间:2017-09-20 18:06:46

标签: arrays bash for-loop

我正在尝试制作一个执行以下操作的bash脚本:

  1. 通过递归搜索dir和subdir的
  2. 来创建文件路径数组
  3. 遍历数组,为数组中的每个文件创建校验和,并将文件路径和文件校验和存储在自己的文件中。
  4. 如果先前对文件进行了哈希处理,则应删除旧行,然后使用更新的校验和替换旧行。对于每个元素,在文件中搜索文件路径,其中存储了具有校验和的文件路径。如果找到,则filecount变量存储匹配量,并使用此变量来确定是应该替换文件还是仅添加文件。
  5. 问题是删除包含先前存储的文件路径/校验和的行的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命令?

2 个答案:

答案 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。如果不使用catecho也可以追加。{/ p>