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.

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
  • 1
    sed -i "\#${tmppath}#d" list.txt will do the same without leaving behind that empty line. – Tim Kennedy Jan 22 '18 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. – John Smith Jan 22 '18 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. – Tim Kennedy Jan 22 '18 at 21:34
  • Thank you all for answers. Solution suggested by Tim Kennedy looks the easiest for me. – Mike Naplet Jan 23 '18 at 17:36
  • @MikeNaplet good reason to upvote his comments) – John Smith Jan 23 '18 at 20:22
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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.