24

My script:

    #!/usr/bin/env bash
    PATH=/home/user/example/foo/bar
    mkdir -p /tmp/backup$PATH

And now I want to get first folder of "$PATH": /home/

    cd /tmp/backup
    rm -rf ./home/
    cd - > /dev/null

How can I always detect the first folder like the example above? "dirname $PATH" just returns "/home/user/example/foo/".

Thanks in advance! :)

checker284
  • 1,286
  • 3
  • 14
  • 29

7 Answers7

42

I've found a solution:

    #/usr/bin/env bash
    DIRECTORY="/home/user/example/foo/bar"
    BASE_DIRECTORY=$(echo "$DIRECTORY" | cut -d "/" -f2)
    echo "#$BASE_DIRECTORY#";

This returns always the first directory. In this example it would return following:

    #home#

Thanks to @condorwasabi for his idea with awk! :)

checker284
  • 1,286
  • 3
  • 14
  • 29
  • 10
    If your path is relative and looks like this: `dir1/in/dir2` then you should target the field `-f1` instead of `-f2` – dmeu Apr 05 '16 at 07:39
7

You can try this awk command:

 basedirectory=$(echo "$PATH" | awk -F "/" '{print $2}')

At this point basedirectory will be the string home Then you write:

rm -rf ./"$basedirectory"/
condorwasabi
  • 616
  • 6
  • 19
  • This looks good, but it does not work. $basedirectory is always empty. But thanks! :) – checker284 Jul 09 '14 at 18:45
  • 2
    Glad you found a solution. Anyway you were right, I just edited the script. I don't know why I wrote `{print $1}`, I also tested it before posting it. Now it should work. – condorwasabi Jul 10 '14 at 07:57
  • This also works to get the nth directory along a path e.g. `basedirectory=$(echo "$PATH" | awk -F "/" '{print $3}')` – WalksB Nov 01 '21 at 18:09
  • replace $2 with $n where n is the nth directory location after first '/' in the path – Jasmeet Singh Jul 28 '22 at 03:51
6

If PATH always has an absolute form you can do tricks like

ROOT=${PATH#/} ROOT=/${ROOT%%/*}

Or

IFS=/ read -ra T <<< "$PATH"
ROOT=/${T[1]}

However I should also add to that that it's better to use other variables and not to use PATH as it would alter your search directories for binary files, unless you really intend to.

Also you can opt to convert your path to absolute form through readlink -f or readlink -m:

ABS=$(readlink -m "$PATH")

You can also refer to my function getabspath.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
4

To get the first directory component of VAR:

echo ${VAR%${VAR#/*/}}

So, if VAR="/path/to/foo", this returns /path/.

Explanation:

${VAR#X} strips off the prefix X and returns the remainder. So if VAR=/path/to/foo, then /*/ matches the prefix /path/ and the expression returns the suffix to/foo.

${VAR%X} strips off the suffix X. By inserting the output of ${VAR#X}, it strips off the suffix and returns the prefix.

If you can guarantee that your paths are well formed this is a convenient method. It won't work well for some paths, such as //path/to/foo or path/to/foo, but you can handle such cases by breaking down the strings further.

Alcamtar
  • 1,478
  • 13
  • 19
1

To get the first firectory:

path=/home/user/example/foo/bar
mkdir -p "/tmp/backup$path"
cd /tmp/backup
arr=( */ )
echo "${arr[0]}"

PS: Never use PATH variable in your script as it will overrider default PATH and you script won't be able to execute many system utilities

EDIT: Probably this should work for you:

IFS=/ && set -- $path; echo "$2"
home
anubhava
  • 761,203
  • 64
  • 569
  • 643
0

Pure bash:

DIR="/home/user/example/foo/bar"
[[ "$DIR" =~ ^[/][^/]+ ]] && printf "$BASH_REMATCH"

Easy to tweak the regex.

Thom
  • 524
  • 1
  • 6
  • 12
-1

You can use dirname...

#/usr/bin/env bash
DIRECTORY="/home/user/example/foo/bar"
BASE_DIRECTORY=$(dirname "${DIRECTORY}")
echo "#$BASE_DIRECTORY#";

Outputs the following...

/home/user/example/foo
RobLoach
  • 2,066
  • 1
  • 12
  • 5