Operating System - Linux
1827806 Members
2277 Online
109969 Solutions
New Discussion

Re: Expand a path passed to a script

 
SOLVED
Go to solution
Steve Tesch
Advisor

Expand a path passed to a script

I'm working in HP-UX 11.11 using the ksh shell. Does anyone know how I can expand a path that has been passed as a parameter to a script?

For example, if the current directory is "/database/app" and the user passes "../bin", I need to expand it to "/database/bin". Or if the current directory is "/database/app" and the user passes "../bin/myfile.txt" I need it to expand to "/database/bin/myfile.txt".

I've come up with a way to brute force the result but I have to believe there's an easier way. I've included my brute force method in an attachment.

Any help would be appreciated.
24 REPLIES 24
Victor Fridyev
Honored Contributor

Re: Expand a path passed to a script

Hi,

If you need to use expanded path in the script, use, if the path is the first parameter:
PATH=$PATH:$PWD/$1
If you want to expand path for your interactive shell, run

. script dirname

after the shell prompt.
The script should contain the same string

HTH
Entities are not to be multiplied beyond necessity - RTFM
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

Hi Steve:

I don't understand whell what you need to do, because if are in /database/app and you use the ../bin or replace by /database/bin, you have the same results. I don't see the difference.
Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
Steve Tesch
Advisor

Re: Expand a path passed to a script

Victor,
Ivan,

Apparently my original explanation was not clear. When I stated that I need to be able to expand a path, I did not mean PATH, I was simply referring to any combination of typed directories the user may pass to a script, which is why I included examples.

As to the reason this is required; while you are correct that the examples I gave are equivalent within the shell, the relative paths have no meaning to another user viewing the results unless they know where the script was run from in the first place. This particular script can be run from anywhere on the system and the results have to indicate absolute paths in order to make any sense.

If that were the only issue, simply reporting the starting directory would reoslve the problem. However, absolute paths are a must when the results have to be sortable in a spreadsheet by path. Attempting to sort relative paths and make any sense of them is impossible.

I hope this helps clarify what I'm looking for.

Steve
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

What if you simply use:

APP_PATH=/database/app

Then, in your script, always use:

$APP_PATH/$1

So, if APP_PATH is /database/app, and the user passes ../bin, doest matter where he is, he will go to

/database/app/../bin -> /database/bin
Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
James R. Ferguson
Acclaimed Contributor

Re: Expand a path passed to a script

Hi Steve:

# cat getpath
#!/usr/bin/sh
pwd
echo ${1}
WHERE=`perl -le 'use Cwd qw(realpath);print realpath $ARGV[0];' $1`
echo ${WHERE}

For example:

# cd /var/tmp/dummydir && ./getpath ../bin
/var/tmp/dummydir
../bin
/var/tmp/bin

Does that help? This is based on the realpath() C library function.

Regards!

...JRF...
Steve Tesch
Advisor

Re: Expand a path passed to a script

Victor,

Again, the issue isn't manipulating directories within the shell, it's being able to report the absolute path, even if the user specified a relative one.

The answer is straight-forward if the user actually passes a directory but if they pass a filename, it gets much trickier as you can see from the brute force method I uploaded.

Steve
Steve Tesch
Advisor

Re: Expand a path passed to a script

James,

Your answer looks like it's on the right track but I get the following error when i attempt to run it:

Can't locate Cwd.pm in @INC (@INC contains: /opt/perl5/lib/5.00502/PA-RISC1.1 /opt/perl5/lib/5.00502 /opt/perl5/lib/site_perl/5.005/PA-RISC1.1 /opt/perl5/lib/site_perl/5.005 .) at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

Any thoughts?

Steve
Leif Halvarsson_2
Honored Contributor

Re: Expand a path passed to a script

Hi,
Just one simple idea.
Is the commands "basename" and "dirname" of any help ?

dirname return the directory part of a path and, basename the filename.
James R. Ferguson
Acclaimed Contributor

Re: Expand a path passed to a script

Hi Steve:

It appears that the 'Cwd' module required isn't in your rather old version of perl.

You could download the module from CPAN:

http://search.cpan.org/~kwilliams/PathTools-3.15/Cwd.pm

...or better, yet, upgrade your version of perl:

http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=PERL

Regards!

...JRF...
Steve Tesch
Advisor

Re: Expand a path passed to a script

First, my apologies, I addressed a previous reply to Victor when it should have been addressed to Ivan.

Leif - Thanks for the input but dirname and basename do not expand relative paths. They were one of my first attempts.

James - I appricate the quick response. I'll look into updating my perl and let you know how it turns out.

Thanks to all,

Steve
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

Still trying:

APP_PATH=/database/app
FULLPATH=`cd $APP_PATH/$1; pwd`
echo $FULLPATH
Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

And going, and going...


APP_PATH=/var/adm/syslog
RELATIVE=`echo $1 |grep "^\."|wc -l`

# If the arg starts with dot, then is a relative path, else just use the specified path
if [ $RELATIVE -gt 1 ]; then
REALPATH=`cd $APP_PATH/$1;pwd`
fi
Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
James R. Ferguson
Acclaimed Contributor

Re: Expand a path passed to a script

Hi Steve:

The perl update is quick and simple and so, so worthwhile. Perl 5.8.x has incorporated lots of good things into its core.

Regards!

...JRF...
Steve Tesch
Advisor

Re: Expand a path passed to a script

Ivan,

Your solution works if the user passes a directory, and is very similar to the method I uploaded. However if they are passing a filename, it gets an error.

I need a solution for both possibilities.

Thanks for the continued effort.

Steve
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

Sorry, I did not see your previous reply addressed to victor (me) about the file.

Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
Steve Tesch
Advisor

Re: Expand a path passed to a script

Ivan,

Your new solution works in most cases but not all. If you pass it a sub-directory of the current directory, it will return the current directory, instead of the full path to the sub-directory.

Your first solution did not have this problem. Also, this solution still can't handle a filename.

Thanks again,

Steve
Leif Halvarsson_2
Honored Contributor

Re: Expand a path passed to a script

CUR=/abc/def
DIR=$(dirname ../xyz/abc.txt)
FILE=$(basename ../xyz/abc.txt)

cd $DIR
ABSOLUTE=$(pwd)

FULL_PATH=${ABSOLUTE}/${FILE}

it should work also with an absolute path or a filename only

Rodney Hills
Honored Contributor
Solution

Re: Expand a path passed to a script

You could compile the following c program that takes a path as its only argument and returns the real path. (Even compiles with the brain dead supplied cc compiler).

#include
main(argc,argv,envp)
int argc;
char *argv[],*envp[];
{
char realp[255];
(void)realpath(argv[1],realp);
printf("%s\n",realp);
exit(0);
}

HTH

-- Rod Hills
There be dragons...
Steve Tesch
Advisor

Re: Expand a path passed to a script

Leif,

Very close! However, if the user passes a path or filename that is already in absolute format (i.e. /home), your solution doubles the initial forward slash (i.e. //home). If they pass the root directory, it returns three forward slashes (i.e. ///).

Thanks for the effort,

Steve
Ivan Ferreira
Honored Contributor

Re: Expand a path passed to a script

Hi, me again, check this sample:

APP_PATH=/var/adm/syslog
RELATIVE=`echo $1 |grep "^\."|wc -l`

# If the arg starts with dot, then is relative
if [ $RELATIVE -gt 0 ]; then
if [ -d $APP_PATH/$1 ]; then
REALPATH=`cd $APP_PATH/$1;pwd`
else
FILEDIR=`dirname $APP_PATH/$1`
REALDIRPATH=`cd $FILEDIR;pwd`
FILENAME=`basename $APP_PATH/$1`
REALPATH=`echo "$REALDIRPATH/$FILENAME"`
fi
else
REALPATH=$1
fi

echo $REALPATH
Por que hacerlo dificil si es posible hacerlo facil? - Why do it the hard way, when you can do it the easy way?
Steve Tesch
Advisor

Re: Expand a path passed to a script

Rodney,

Excellent solution!

Not having much experience with compiling programs for Unix, I compiled it with no options and it works perfectly. None of the tests I've run have failed (unless the user provides a bogus entry but then there are larger problems anyway).

This has the added convenience of completely encapsulating the code in a single command for use in my scripts, keeping the complexity of the scripts themselves to a minimum.

I'm still going to upgrade my perl and check out that solution but I'm going to be using this as the permanent fix.

Thanks!

Steve
Steve Tesch
Advisor

Re: Expand a path passed to a script

Ivan,

I appreciate the effort but what your suggesting is already as large as the brute force method I uploaded at the beginning of this thread.

As you can see from the previous post, Rodney posted a simple C program that will wrap it all up nicely for me.

Thanks,

Steve
James R. Ferguson
Acclaimed Contributor

Re: Expand a path passed to a script

Hi (again) Steve:

...and I can't resist noting that Rodney's C-code leverages the 'realpath()' function that the perl module I suggested you use does. :-;

Regards!

...JRF...
Steve Tesch
Advisor

Re: Expand a path passed to a script

As a final follow up to the perl solution. I found that there are actually two versions of perl currently loaded on my system, version 5 and a newer version 5.6.1.

I was able to get the perl solution to work by pointing it to the newer version as shown here:

#!/bin/ksh

WHERE=`perl5.6.1 -le 'use Cwd qw(realpath);print realpath $ARGV[0];' $1`
echo $WHERE

Actually, I will likely use the perl solution in some cases and the compiled C solution in others.

The difference is, as provided above, the perl solution will generate an error if an invalid directory is passed, while the C solution will not.

Each solution has it's own merits depending on what exactly you're trying to accomplish and if/how you're going to handle invalid paths.

I want to thank everyone on this forum for their prompt responses and dedication to helping me find a workable solution. This has been a very enjoyable first experience.

Steve