LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-22-2009, 03:27 AM   #16
rainbowbird
LQ Newbie
 
Registered: Apr 2009
Location: China, Shanghai
Distribution: Fedora 7
Posts: 2

Rep: Reputation: 5
a little modification


Quote:
Originally Posted by Disillusionist View Post
Code:
source="./tmp/myfile"
dest=~/.Waste/$(echo $source|sed "s@^./@$PWD@"|sed "s@^/@@")
Disillusionist:
a little modifiation
Code:
source="./tmp/myfile"
dest=~/.Waste/$(echo $source|sed "s@^./@$PWD/@"|sed "s@^/@@")
 
Old 09-07-2009, 02:34 PM   #17
kj6loh
Member
 
Registered: Jun 2004
Posts: 47

Rep: Reputation: 17
Quote:
Originally Posted by Andy Alkaline View Post
I'd like to be able to move the file into ~/.Waste/original/path

Using $PWD doesn't guarantee that. I need to have the absolute path of the file returned.

(a few minutes later)
Found it.
Bash equivalent for PHP realpath()
Unfortunately readlink is not on every bash system
 
1 members found this post helpful.
Old 11-02-2009, 06:55 PM   #18
edvalson
LQ Newbie
 
Registered: May 2009
Posts: 1

Rep: Reputation: 0
Quote:
What is your concern with using $PWD? If concerned about someone exporting variables to an incorrect value, you could always use $(pwd) to set the value of PWD.
Because if you write scripts using absolute paths that are not depending on a) where the script starts from, or b) from cd'ing somewhere inside the script, $PWD is irrelevant.

ta0kira has it right: to return the absolute path of a filename that is originally given with a relative path:

for example you are at a bash prompt in /dir1/dir2/dir3/dir4

and the file is /dir1/dir2/file1

ABSOLUTE_DIR=$(dirname $(readlink -f ../../dir2/file1))
 
Old 08-25-2010, 05:16 AM   #19
kwutchak
LQ Newbie
 
Registered: Jul 2009
Location: Singapore
Distribution: Gentoo, Kubuntu
Posts: 4

Rep: Reputation: 0
Lightbulb A solution I found elsewhere...

echo "Absolute path: `cd $1; pwd`"

http://peasleer.wordpress.com/2007/0...-path-in-bash/
 
Old 08-25-2010, 10:50 AM   #20
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Another solution is to use the external pwd command instead of the bash builtin. In the following illustration /home/c/Templates is a symlink to /home/c/d/Templates
Code:
c@CW9:~$ ls -l Templates
lrwxrwxrwx 1 c users 11 2010-06-07 11:43 Templates -> d/Template
c@CW9:~$ cd Templates
c@CW9:~/Templates$ pwd
/home/c/Templates
c@CW9:~/Templates$ echo $PWD
/home/c/Templates
c@CW9:~/Templates$ /bin/pwd
/home/c/d/Templates
 
1 members found this post helpful.
Old 12-28-2010, 02:58 PM   #21
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
I didn't know readlink was nonstandard. Thanks to the suggestions, this is what I've come up with.

Code:
#!/bin/bash
# abspath.sh
# Find absolute path of file or symbolic link without using readlink
# December 28, 2010

function absp() {
  local FILE=$1
  local CWD=$(pwd)
  
  # remove trailing slash
  FILE=${FILE%/}

  local FBN=`basename "$FILE"`

  # Remove basename to get relative path

  local RP="${FILE%$FBN}"
  
  # change dir to relative path to run pwd
  cd "$RP"

  # Assign present working dir to $MOVETO; pwd returns the
  # absolute path
  AP=$(pwd)
	
  # Append filename to abs path
  APFN=$(pwd)/$FBN

  # Change back to directory we started in
  cd "$CWD"
  
#  echo -e "\n\tAbsolute path:"
#  echo -e "\t$AP"
#  echo -e "\n\tAbsolute path to file:"
#  echo -e "\t$APFN\n"
  
  return 0
}

absp $1
echo -e "\n\tAbsolute path:"
echo -e "\t$AP"
echo -e "\n\tAbsolute path to file:"
echo -e "\t$APFN\n"
exit 0
 
Old 12-28-2010, 03:53 PM   #22
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
I like this better:

Code:
#!/bin/bash
# abspath.sh 0.01
# Find absolute path of file or symbolic link without using readlink
# December 28, 2010

function absp() {

# Call this function by
# VAR=`absp <filename> ap|apfn>` # backticks required
# ap will return absolute path; apfn will return absolute path with filename

  local FILE=$1
  local CWD=$(pwd)
  
  # remove trailing slash
  FILE=${FILE%/}

  local FBN=`basename "$FILE"`

  # Remove basename to get relative path

  local RP="${FILE%$FBN}"
  
  # change dir to relative path to run pwd
  cd "$RP"

  # Assign present working dir to $MOVETO; pwd returns the
  # absolute path
  local AP=$(pwd)
	
  # Append filename to abs path
  local APFN=$(pwd)/$FBN

  # Change back to directory we started in
  cd "$CWD"
  
  case $2 in
  ap)
  echo "$AP"
  ;;
  apfn)
  echo "$APFN"
  ;;
  *)
  echo "NULL";return 1;break
  ;;
  esac
  
  return 0
}

# absp function takes two parameters; file name and ap|apfn
# This method allows different variable names for AP or APFN throughout the program

ABSOLUTE_PATH=`absp $1 ap`
ABSOLUTE_FILE=`absp $1 apfn`

echo $ABSOLUTE_PATH
echo $ABSOLUTE_FILE

exit 0
 
Old 01-24-2011, 02:50 AM   #23
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
I made another change. In the previous function I posted, it has to be called three times if the absolute path, absolute path with filename, and base filename are required. That can slow things down. This method may be slightly more memory intensive, but speeds up the process.

Code:
function gfp_info() {

  local FILE=$1
  
  # save pwd to cd back to it below
  local CWD=$(pwd)
  
  # remove trailing slash
  FILE=${FILE%/}

  # Get the basename of the file
  local file_basename=`basename "$FILE"`

  # Remove basename to get relative path
  # Using bash's string function instead of calling
  # dirname
  local RP="${FILE%$file_basename}"

  # change dir to relative path
  cd "$RP"

  # Assign present working dir to $fileap; pwd returns the
  # absolute path
  local fileap=$(pwd)
	
  # Append base filename to absolute path
  local ap_with_basename=$(pwd)/$file_basename

  # Change back to directory we started in
  cd "$CWD"
  
  AP="${fileap}"
  APFN="${ap_with_basename}"
  FBN="${file_basename}"

  return 0

}

# Initialize variables used in function so they can be used globally
AP=""
APFN=""
FBN=""

gfp_info "$FILENAME"

# The three variables above will now have value.
 
Old 01-24-2011, 10:50 AM   #24
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
It could go a little faster if:
  1. local CWD=$(pwd) was removed and cd "$CWD" was changed to cd -
  2. file_basename=`basename "$FILE"` was changed to file_basename="${FILE##*/}"
  3. fileap=$(pwd) was changed to fileap=$PWD
  4. ap_with_basename=$(pwd)/$file_basename was changed to ap_with_basename=$fileap/$file_basename or ap_with_basename=$PWD/$file_basename. In the latter case $fileap need not be used if suggestion 6 is implemented.
  5. AP=""
    APFN=""
    FBN=""
    were removed; these variables are created as global variables by assigning values to them in the function.
  6. AP="${fileap}" were moved prior to cd "$CWD" in which case $fileap need not be used if suggestion 4, second option is implemented.
Incidentally ...

pwd does not return the absolute path if the path was reached via a symlink in which case pwd -P is needed:
Code:
c@CW8:~$ cd /tmp
c@CW8:/tmp$ mkdir foo
c@CW8:/tmp$ ln -s foo bar
c@CW8:/tmp$ cd bar
c@CW8:/tmp/bar$ pwd
/tmp/bar
c@CW8:/tmp/bar$ pwd -P
/tmp/foo
RP="${FILE%$file_basename}" does not generate a relative path; it extracts the directory component of the full path. A relative path is one that does not begin with "/". The same could be achieved by the common idiom RP=${FILE%/*} (the double quotes are not necessary on the RHS of an assignment "=". Strictly speaking these are not "bash string functions" but bash parameter expansions.
 
1 members found this post helpful.
Old 01-24-2011, 10:51 AM   #25
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by catkin View Post
Another solution is to use the external pwd command instead of the bash builtin.
That works but using the pwd builtin with the -P option is faster.
 
1 members found this post helpful.
Old 01-25-2011, 03:39 PM   #26
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
I've made the changes to my script, with some exceptions.

cd "-" &>/dev/null

And when I was using rmw on a file in my present working directory, RP=${FILE%/*} would kick out an error. (No slash to find)

Thanks for the suggestions, catkin. Good stuff.
 
Old 01-26-2011, 03:28 AM   #27
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by Andy Alkaline View Post
And when I was using rmw on a file in my present working directory, RP=${FILE%/*} would kick out an error. (No slash to find)
Strange; it should silently do nothing as in
Code:
c@CW8:/tmp$ FILE=foo
c@CW8:/tmp$ var=${FILE%/*}
c@CW8:/tmp$ echo $var
foo
 
Old 01-26-2011, 01:20 PM   #28
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
I was wrong about the slash, but the code you suggested assigns the basename, whereas I want everything except for the basename. Since I'm not good at explaining, allow me to illustrate:

Code:
  # extracts the directory component of the full path
#  local DC="${FILE%$file_basename}"
  local DC="${FILE%/*}"
  echo -e $c_1"FILE: $FILE"$c_reset
  cd "$DC"
  echo -e $c_1"DC: \"$DC\" pwd: - \"$(pwd -P)\" "$c_reset
  # Assign present working dir to $fileap; pwd returns the
  # absolute path
  local fileap=$(pwd -P)
andy@pigeon:~/Documents$ rmw temp
FILE: temp
/home/andy/bin/rmw: line 451: cd: temp: Not a directory
DC: "temp" pwd: - "/home/andy/Documents"
`temp' -> `/home/andy/.Waste/files/temp.2011-01-26h13m11s43'

---

Code:
  # extracts the directory component of the full path
  local DC="${FILE%$file_basename}"
#  local DC="${FILE%/*}"
  echo -e $c_1"FILE: $FILE"$c_reset
  cd "$DC"
  echo -e $c_1"DC: \"$DC\" pwd: - \"$(pwd -P)\" "$c_reset
  # Assign present working dir to $fileap; pwd returns the
  # absolute path
  local fileap=$(pwd -P)
andy@pigeon:~/Documents$ rmw temp
FILE: temp
DC: "" pwd: - "/home/andy/Documents"
`temp' -> `/home/andy/.Waste/files/temp.2011-01-26h13m14s23'

I've added an if clause around cd $DC
Code:
if [ $DC ]; then  
    cd "$DC"
  fi
If in the same dir as the file, no need to tell cd to change to nothing and waste everyone's time.

Last edited by Andy Alt; 01-26-2011 at 01:26 PM. Reason: Add modification
 
Old 01-26-2011, 11:41 PM   #29
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
For the basename: basename=${fullpath##*/}. It looks like this at the command prompt:
Code:
c@CW8:/tmp$ fullpath=/etc/rsyncd.conf
c@CW8:/tmp$ basename=${fullpath##*/}
c@CW8:/tmp$ echo $basename
rsyncd.conf
 
Old 01-27-2011, 09:37 AM   #30
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Manjaro, Debian64 stable
Posts: 528

Original Poster
Rep: Reputation: 167Reputation: 167
Code:
function gfp_info() {

# Thanks to catkin for the massive improvements to this function
# http://www.linuxquestions.org/questions/user/catkin-444761/

  local FILE=$1
  
  # remove trailing slash
  FILE=${FILE%/}

  # Get the basename of the file
  local file_basename="${FILE##*/}"

  # extracts the directory component of the full path
  local DC="${FILE%$file_basename}"

  if [ $DC ]; then  
    cd "$DC"
  fi

  # Assign present working dir to $fileap; pwd returns the
  # absolute path
  local fileap=$(pwd -P)
	
  # Append base filename to absolute path
  local ap_with_basename=$fileap/$file_basename

  # Change back to directory we started in
  cd "-" &>/dev/null
  
  AP="${fileap}"
  APFN="${ap_with_basename}"
  FBN="${file_basename}"

  return 0

}
 
  


Reply

Tags
bash, bin, can, command substitution, console, link, mv, path, php, recycle, rm, scripts, sed, symbolic, trash



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
ls - Do not list full path only filename baddah Linux - General 12 06-17-2013 12:21 AM
bash - return home path babag Programming 2 06-01-2008 04:59 PM
Getting the first part of a filename in a BASH script trevelluk Programming 3 02-15-2005 01:06 AM
php mail script return path richard22 Linux - Software 1 08-22-2003 04:10 AM
bash script - incrementing a filename in a script tslinux Programming 10 08-05-2003 11:58 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:01 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration