2

In tcsh I can extract second path element from the end of path by following way

cd /some/long/directory/structure/path/
set x=`pwd`
echo ${x:h:h:t}
directory

How can I do the same in bash?

I mean , does bash also have this kind of modifiers?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Roman Kaganovich
  • 618
  • 2
  • 6
  • 27
  • This is very closely related to, if not outright duplicative of, [How to get name of second last folder in linux](https://stackoverflow.com/questions/13267126/how-to-get-name-of-second-last-folder-in-linux) or [How to get the last part of dirname in bash](https://stackoverflow.com/questions/23162299/how-to-get-the-last-part-of-dirname-in-bash). – Charles Duffy Feb 08 '19 at 20:41
  • 1
    @CharlesDuffy It is not. This question is about modifiers and not about "how to extract n's element from path" – Roman Kaganovich Feb 09 '19 at 08:18
  • However, such "modifiers" (in bash, these are all referred to as [parameter expansion](https://wiki.bash-hackers.org/syntax/pe) forms) are all subsets of means to achieve your goal. Thus, the preexisting Q&A entries linked above *do* discuss them -- see [this answer](https://stackoverflow.com/a/44350542/14122) for an example. – Charles Duffy Feb 09 '19 at 13:09
  • And frankly, if you're restricting your answer from "how do I do X in bash?" to "how do I do X in bash using a direct analog to syntax Y?", I question whether that question is *practical* in nature, as required by [our on-topic definition](https://stackoverflow.com/help/on-topic). (If you know *a* means to do X, it's fair to ask for a faster one or a terser one, but one that's different *just because*... well, what's the practical point?) – Charles Duffy Feb 09 '19 at 13:10
  • 1
    @CharlesDuffy ... and frankly, yes Charles, this question is very practical. Otherwise I wasn't asked it :-) . Thanks to jhnc , chepner and many other stackoverflow users who published the solution and not tried to show how "smart" they are regarding to "our topic definition". Guys - you really helped me. Thanks a lot! – Roman Kaganovich Feb 09 '19 at 18:14

3 Answers3

3

The csh-style modifiers can be used with history expansion (unsurprisingly, because history expansion was borrowed from csh).

$ cd /some/long/directory/structure/path/
$ echo !!:1:h:h:t
echo directory
directory

!!:1 selects word 1 (counting from zero) of the previous command, so the argument to cd.

(echo directory appears on standard error because the shell defaults to displaying the result of history expansion before actually executing the resulting command.)

chepner
  • 497,756
  • 71
  • 530
  • 681
2

In a non-interactive bash script, history expansion commands as in @chepner's answer won't normally be available. However, you do have parameter expansions like:

$ cd /some/long//directory///structure/path/
$ set x=$(pwd)
$ echo $x
/some/long/directory/structure/path
$ y=${y%/*/*}      # each /* is equivalent to one :h
$ y=${y##*/}       # equivalent to :t
$ echo $y
directory
jhnc
  • 11,310
  • 1
  • 9
  • 26
  • History expansion isn't line editing, and can be enabled for non-interactive shells (though I wouldn't recommend it). – chepner Feb 09 '19 at 14:04
0
cd /some/long/path/somewhere
x=$PWD
basename "$(dirname "$x")"
>  path

dirname gets the absolute path of the parent folder of the argument. basename gets the name of the argument.

Edit: remembered the much better way than I was doing before.

jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
  • `$PWD` shouldn't have trailing slashes. If it may, `y=${x%%/}` will strip any. Perhaps worth annotating in your answer what equates to `:h` and what to `:t` – jhnc Feb 08 '19 at 20:28
  • @jhnc, remembered a better way – jeremysprofile Feb 08 '19 at 20:35
  • 1
    You mean `basename "$(dirname "$x")"`, right? Just `x` doesn't look at the variable's value, and without the quotes, directory names with spaces will misbehave. – Charles Duffy Feb 08 '19 at 20:36
  • that's not exactly bash though. could just as well feed it into perl if you're going to do it that way. :p – jhnc Feb 08 '19 at 20:37