【问题标题】:Bash, deleting specific row from fileBash,从文件中删除特定行
【发布时间】:2018-08-31 12:28:20
【问题描述】:

我有一个文件名和文件路径 我想删除那些不再存在的文件的行

file.txt(目前所有现有文件):

file1;~/Documents/test/123
file2;~/Documents/test/456
file3;~/Test
file4;~/Files/678

现在,如果我删除任何给定文件(例如文件 2 和文件 4)并运行我的脚本,我希望它测试给定行中的文件是否存在,如果不存在则删除该行

file.txt(删除file2、file4后):

file1;~/Documents/test/123
file3;~/Test

到目前为止我得到了什么(根本没有工作): - 根本不想跑

#!/bin/sh
  backup=`cat file.txt`
rm -f file.txt
  touch file.txt

  while read -r line
  do
    dir=`echo "$line" | awk -F';' '{print $2}'`
    file=`echo "$line" | awk -F';' '{print $1}'`

    if [ -f "$dir"/"$file" ];then
        echo "$line" >> file.txt
    fi
  done << "$backup"

【问题讨论】:

  • 我不是 100% 明白,但您可能想首先将 done &lt;&lt; "$backup" 更改为 done &lt; "$backup"
  • 错误...对不起,读错了。由于$backup 不是文件名,因此您不能这样重定向。我建议要么将$backup 转换为文件名,要么执行done &lt; &lt;(echo "$backup")&lt;&lt; 运算符用于 HERE 文档,而不是重定向。
  • 请注意,我认为波浪号 '~' 不会在 shell 脚本中扩展,我认为它被视为字符串文字
  • 读取输入文件,一次一行。如果当前行指示的文件存在,则将其添加到 bash 数组中。在循环结束时,用数组内容覆盖输入文件。

标签: bash file awk


【解决方案1】:

这是一种方法:

tmp=$(mktemp)
while IFS=';' read -r file rest; do
   [ -f "$file" ] && printf '%s;%s\n' "$file" "$rest"
done < file.txt > "$tmp" && mv "$tmp" file.txt

或者如果您出于某种原因不需要临时文件:

tmp=()
while IFS=';' read -r file rest; do
   [ -f "$file" ] && tmp+=( "$file;$rest" )
done < file.txt &&
printf '%s\n' "${tmp[@]}" > file.txt

两者都未经测试,但如果不完全正确,应该非常接近。

【讨论】:

    【解决方案2】:

    如果我理解,应该这样做。

    touch file.txt file2.txt
    
    for i in `cat file.txt`; do
      fp=`echo $i|cut -d ';' -f2`
       if [ -e $fp ];then
           echo "$i" >> file2.txt
       fi
    done
    mv file2.txt file.txt
    

    【讨论】:

    • 有什么办法不使用第二个文件?
    • @DennisVymer 是的,请参阅我 2 小时前的评论。
    • 我没有投反对票,但它充满了错误和反模式,所以也许这就是原因?
    猜你喜欢
    • 2018-06-16
    • 2018-08-25
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 2018-10-08
    • 2017-11-23
    • 1970-01-01
    • 2011-08-13
    相关资源
    最近更新 更多