29

How to cut the last field in this shell string

LINE="/string/to/cut.txt"

So that the string would look like this

LINE="/string/to/"

Thanks in advance!

user558134
  • 1,071
  • 6
  • 25
  • 38

5 Answers5

73

For what it's worth, a cut-based solution:

NEW_LINE="`echo "$LINE" | rev | cut -d/ -f2- | rev`/"
Lucas Jones
  • 19,767
  • 8
  • 75
  • 88
  • I believe this is cutting off the first field, not the last? – Michael Mar 07 '12 at 22:22
  • @Michael: I ran it through some tests here, and it seems to work fine. It does actually cut the first field, but it (rather inefficiently) reverses the string before and after, which has the desired overall effect. – Lucas Jones Mar 10 '12 at 16:42
  • 8
    I can confirm this does indeed work, in both Unix and GNU implementations of cut. Obviously the dirname answer is better for the OPs specific use case, but I found this when searching for a general way to drop the last field with cut and this was it. – jdeuce Jul 23 '12 at 18:04
  • 1
    @LucasJones It's worth noting that this is many, many times more efficient on multiline input, because `dirname` can only be run on one path at a time. For example, on `find` output the `dirname` alternative is `find ... -exec dirname {} \;`. The `-exec` makes it extremely slow. – Nicole Aug 28 '13 at 06:40
23

I think you could use the "dirname" command. It takes in input a file path, removes the filename part and returns the path. For example:

$ dirname "/string/to/cut.txt"
/string/to
Sebastian Zartner
  • 18,808
  • 10
  • 90
  • 132
user554272
  • 278
  • 3
  • 7
18

This will work in modern Bourne versions such as Dash, BusyBox ash, etc., as well as descendents such as Bash, Korn shell and Z shell.

LINE="/string/to/cut.txt"
LINE=${LINE%/*}

or to keep the final slash:

LINE=${LINE%/*}/
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • This should be the accepted answer because it is the fastest and most portable solution as it will work in any POSIX-compliant shell without requiring a `fork`. – Adrian Frühwirth Feb 23 '15 at 13:29
1
echo "/string/to/cut.txt" | awk -F'/' '{for (i=1; i<NF; i++) printf("%s/", $i)}'
ajreal
  • 46,720
  • 11
  • 89
  • 119
1

echo $LINE | grep -o '.*/' works too.

mohit6up
  • 4,088
  • 3
  • 17
  • 12