4

Input

/in/archive/ABC/20140111_ABC_018_PART_001.dat

Desired Output:

20140111_ABC_018_PART_001.dat

Command used:

cut -d/ -f4 "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat"

Problem:

Its actually opening the file 20140111_ABC_018_SALESDOC_ITEM_018.dat in the path /1a/ftproot/archive/ABC/ and displaying the result from file.

Timo
  • 6,332
Rakesh K
  • 151

2 Answers2

4

Here are a few options:

  1. basename as Stephane suggested

    $ basename /1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat
    20140111_PR1_018_SALESDOC_ITEM_001.dat
    

    basename is part of coreutilsand simply strips the path from file names.

  2. awk

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat" | 
       awk -F'/' '{print $NF}'
    

    The -F option to awk defines the field separator. So,we set that to /and then print the last field ($NF).

  3. cut

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat" |  
       cut -d '/' -f 6
    

    -d is the field separator and -f 6 tells cut to only print the 5th field.

    This is a very limited approach though, since it requires you to know the number of fields in advance. A better way would be to use rev (which reverses it's input) to make the last field first, then cut to get the 1st field and then rev to get it back the way it was:

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat\n" | 
       rev | cut -d/ -f1 | rev
    
  4. Perl

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat\n" |
       perl -pe 's/.+?([^\/]+)$/$1/;'
    

    The -p flag tells perl to print each input line after executing whatever script is given as -e. In this case, we simply tell perlto replace everything up to the longest stretch of non-/ characters. Since this is Perl, there are many ways of doing this:

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat\n" | 
       perl -F/ -ane 'print $F[$#F]'
    

    The -a flag tellsperlto behave like awk, it will automatically split each input line into the @F array. So,we set the field delimiter to / with -F and then print the last element of the array ($F[$#F]). The -n causes perl to loop over it's input line by line.

  5. grep

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat" | 
      grep -Po '[^/]+$'
    

    The -P activates PCREs and the -o means "only print the matched string". So, we tell grep to look for the longest string of non-/ up to the end of the input string ($).

  6. shell

    $ foo="/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat";     
    $ printf "${foo##*/}\n" 
    

    This takes advantage of the shell's string manipulation abilities. Specifically, the construct ${var##pattern} will delete the longest match of pattern from the front of $var. So,##*/means delete everything until the last /.

  7. sed

    $ printf "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat\n" | 
       sed 's/.*\///'
    

    sed will substitute everything up to the last /.

terdon
  • 242,166
2

You should echo the string into cut:

echo "/1a/ftproot/archive/ABC/20140111_PR1_018_SALESDOC_ITEM_001.dat" | cut -d/ -f6

(note that the field # is 6)

But Stephane's comment using basename is a better way to do that.

Timo
  • 6,332
  • 3
    Note that for arbitrary data, you should not use echo but printf instead. Also note that cut cuts the fields of each line of input, so it can't be used for arbitrary filenames as filenames can be made of several lines. – Stéphane Chazelas Jan 14 '14 at 10:13
  • @StephaneChazelas Thank you. Should I delete my answer or update? I think what is still good is that it explains why things went wrong the way Rakesh did. – Timo Jan 14 '14 at 10:26
  • Yes.. Actually I was using this in shell script.. and it did not work... I had to use awk and print – Rakesh K Jan 14 '14 at 10:31
  • display=$(echo ${file} |awk -F"/" '{print $6}') .. here $file holds the string i want to edit. – Rakesh K Jan 14 '14 at 10:32
  • Like Stephane wrote, you will have problems if the filename has newlines. Important is that cut does not take a commandline parameter as sting but if a parameter is there it is used as a filename. – Timo Jan 14 '14 at 10:36