1

I have a string:

//host:/dir1/dir2/dir3/file_name

I want to fetch value of host & directories in different variables in unix script. Example :

host_name = host
dir_path = /dir1/dir2/dir3

Note - String length & no of directories is not fixed.

Could you please help me to fetch these values from string in unix shell script.

3 Answers 3

3

Using bash string operations:

str='//host:/dir1/dir2/dir3/file_name'
host_name=${str%%:*}
host_name=${host_name##*/}
dir_path=${str#*:}
dir_path=${dir_path%/*}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Putnamhill, this solution is almost working for me. echo ${host_name} host echo ${dir_path} /dir1/dir2/dir3/file_name. could you please let me know how can I get only directory path without file name. eg : /dir1/dir2/dir3
Thanks alot for all your help & guidance. I got all three values (host,directory path & file) in this way : str='//host:/dir1/dir2/dir3/file_name' filename=$(basename $str) echo ${filename} file_name host_name=${str%%:*} host_name=${host_name##*/} echo ${host_name} host dir_path=${str#*:} dir_path=${dir_path%%/${filename}*} echo ${dir_path} /dir1/dir2/dir3
@Tamanna, I've added one more string operation to remove /file_name (%/* means strip the shortest match of /* from the right end of the string).
3

I would do it using regular expressions:

if [[ $path =~ ^//(.*):(.*)/(.*)$ ]]; then
    host="${BASH_REMATCH[1]}"
    dir_path="${BASH_REMATCH[2]}"
    filename="${BASH_REMATCH[3]}"
else
    echo "Invalid format" >&2
    exit 1
fi

If you are sure that the format will match, you can do simply

[[ $path =~ ^//(.*):(.*)/(.*)$ ]]
host="${BASH_REMATCH[1]}"
dir_path="${BASH_REMATCH[2]}"
filename="${BASH_REMATCH[3]}"

Edit: Since you seem to be using ksh rather than bash (though bash was indicated in the question), the syntax is a bit different:

match=(${path/~(E)^\/\/(.*):(.*)\/(.*)$/\1 \2 \3})
host="${match[0]}"
dir_path="${match[1]}"
filename="${match[2]}"

This will break if there are spaces in the file name, though. In that case, you can use the more cumbersome

host="${path/~(E)^\/\/(.*):(.*)\/(.*)$/\1}"
dir_path="${path/~(E)^\/\/(.*):(.*)\/(.*)$/\2}"
filename="${path/~(E)^\/\/(.*):(.*)\/(.*)$/\3}"

Perhaps there are more elegant ways of doing it in ksh, but I'm not familiar with it.

1 Comment

+1 Nice solution, though this includes filename which OP doesn't want. Fix would be [[ $path =~ ^//(.*):(.*)/.*$ ]] or better.
0

The shortest way I can think of is to assign two variables in one statement:

$ read host_name dir_path <<< $(echo $string | sed -e 's,^//,,;s,:, ,')

Complete script:

string="//host:/dir1/dir2/dir3/file_name"
read host_name dir_path <<< $(echo $string | sed -e 's,^//,,;s,:, ,')
echo "host_name = " $host_name
echo "dir_path = " $dir_path

Output:

host_name:  host
dir_path:  /dir1/dir2/dir3/file_name

4 Comments

I am getting this error : ksh: 0403-057 Syntax error: `<' is not expected. Could you please guide me on this.
@user3379709 it seems like you are using ksh instead of bash. The question's tags indicate bash, so the answers will assume that.
Interesting solution. I was surprised to see that it works with spaces in the path too (it looked at first glance as if it wouldn't). It doesn't separate out the file name, though.
Bash assigns the string before the first space to variable 1, and the remaining text, including spaces, to variable 2.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.