5

I'm trying to use sed to replace just the last / in the following directory structure, but I'm not able to succeed with this. Any suggestions?

Input is /tmp/ABC/Dirs/, output should be /tmp/ABC/Dirs

echo " /tmp/ABC/Dirs/"  | sed -r "s/\/(?:[a-zA-Z0-9])/g"
  • 1
    @Alex Comments are transient, leave an answer! – grg Jan 6 '18 at 12:05
  • If you're doing this to "clean up" a pathname so that it doesn't confuse the shell, it's not necessary. shells don't get confused by extra / characters. //////path/to///somewhere///filename is just /path/to/somewhere/filename as far as the shell is concerned. BTW, readlink's -e and -f options can be used to canonicalise a pathname to a directory or file (i.e. resolve all symlinks and return the canonical pathname) – cas Jan 6 '18 at 14:20
1

I was the one who answered the question first with my s/\/$// comment.

Other people had time to contribute much fuller answers that day.

SO today -a few days later- I post a redundant answer, because I want the "Peer Pressure" Bronze award gone from the list.

sed -e s./$..g   # You can golf the quotes and the "\" here

So please, good folks, please downvote this time until -3 :)

  • What? No! This was supposed to be a troll answer, meant to be down-voted, so that I could delete It at -3 to get the "Peer Pressure" Bronze award. You foiled that plan by marking mine as the AA. ;) The answers below e.g. from @Stephane are much more comprehensive. But thanks anyway :) – Alex Stragies Jan 13 '18 at 19:54
9

sed seems to be rather overkill here, you can remove a trailing / directly in the Korn shell (and similar shells like bash, and all POSIX compliant shells as that Korn shell feature has been specified by POSIX for the sh utility):

$ foo=/tmp/ABC/Dirs/
$ echo "${foo%/}"
/tmp/ABC/Dirs
  • Thanks for help, worked perfectly. Think this one will be sufficient for my scenario. I was trying more with sed. – KK2486 Jan 6 '18 at 11:40
3

If you wanted to do with with sed, you'd do:

file=/any/path
sed '$s|/$||' << EOF
$file
EOF

That is, remove a / character at the end (second $) of the last (first $) line of the path stored in $file. With some sed implementations that assumes the size in bytes of the greatest sequence of non-newline characters in $file doesn't exceed LINE_MAX (which is often shorter than the maximum size of a path supported in arguments to system calls).

Note that for the special case of / or //, stripping that trailing / may not be desirable. You may also want to remove all trailing / in /foo/bar/// for instance.

So maybe a more advanced one and that would justify sed a bit more would be:

sed '
  ${
    s|\([^/]\)/*$|\1|
    s|^////*|/|
    1b
    s|/*$||
  }' << EOF
$file
EOF

That is preserve // as it is, turn ///, ///// and / into /, but foo// into foo and $'foo\n//' into $'foo\n'.

Note that (?:...) is a perl regexp operator, not extended regexp operator (as recognised by GNU sed with that GNU-specific -r option).

1

You can use perl instead of sed:

echo "/tmp/ABC/Dirs/" | perl -pne  "s/\/$//g"

Output

/tmp/ABC/Dirs
  • You can golf this to perl -pne s./$..g – Alex Stragies Jan 12 '18 at 17:55

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.