0

I have file "list.txt" containing absolute paths to other files

/home/lin/bash/aaa /home/lin/bash/song.mp3 /home/lin/bash/doc.html /home/lin/bash/directory 

I want to assign path to variable

path="/home/lin/bash/song.mp3" 

and then remove whole line with that path. I've tried

sed -i '$path' list.txt 

and many other command with grep, echo but nothing works.

    3 Answers 3

    2

    Try grep approach once again - it'll work:

    grep -xv "$path" list.txt > tmp_$$ && mv tmp_$$ list.txt 

    The final list.txt contents:

    /home/lin/bash/aaa /home/lin/bash/doc.html /home/lin/bash/directory 
      0

      There are two problems with your solution. First since you're using single quotes for '$path' this expression is treated literally, and not like the variable $path. In order to solve this use double quotes "$path". But then you will face the second problem: you want to use slash / as a special sed-symbol and at the same time this symbol is present in paths, which will confuse sed. Therefore you have to use some other symbol instead of slash, for example, use comma

      $ sed -i "s,${path},," list.txt $ cat list.txt /home/lin/bash/aaa /home/lin/bash/doc.html /home/lin/bash/directory 

      There is another beautiful approach, suggested by Tim Kennedy (see explanation of how it works in the discussion below), which does not leave the blank line

      $ sed -i "\,${path},d" list.txt $ cat list.txt /home/lin/bash/aaa /home/lin/bash/doc.html /home/lin/bash/directory 
      5
      • 1
        sed -i "\#${tmppath}#d" list.txt will do the same without leaving behind that empty line.CommentedJan 22, 2018 at 15:49
      • @Tim, beautiful solution, but I do not understand how it works)) p.s. if you do not mind, I will cite you in my answer.CommentedJan 22, 2018 at 16:08
      • 2
        Your solution, "s,${tmppath},," is a sed substitution command. Using a pattern like /pattern/d tells sed to delete the line the pattern is in. Except, in this case, as you rightly pointed out, the delimiter needs to change because the pattern is full of / characters. I should have used commas in my example to make it more similar to yours, so it would be: "\,${tmppath},d". In a nut shell, the delimiters identify the pattern to find, and the d is the delete command. And the leading backslash tells sed to ignore the , as a comma and use it as a delimiter.CommentedJan 22, 2018 at 21:34
      • Thank you all for answers. Solution suggested by Tim Kennedy looks the easiest for me.CommentedJan 23, 2018 at 17:36
      • @MikeNaplet good reason to upvote his comments)CommentedJan 23, 2018 at 20:22
      0

      You could do this with GNU sed and double qoutes to expand the variable.

      sed -i.bak "\:^${path}$:d" list.txt 
      • Here we used -i to have in-place replace/deletion of matched patters as in $path, the .bak is taking a backup of original list.txt file with to list.txt.bak
      • We used different separator to prevent failing sed with slashes / in $path will contain.
      • We used start of line ^ and end of line $ anchors to match the path in whole line not partially if matched.
      • We escaped opening first delimiter as it's mandatory when delimiter is other than slash /. in man sed documented.

        \cregexpc Match lines matching the regular expression regexp. The c may be any character. 

        actually this is telling sed that next character is our delimiter.

      0

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.