LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   bash script - return full path and filename (http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/)

Andy Alkaline 10-31-2008 07:02 PM

bash script - return full path and filename
 
I'm attempting to improve a bash script, ReMove to Waste. It moves files into ~/.Waste and prepends the present working directory to the destination folder under ~/.Waste.

I'd like to have it moved to the same path from where the file or folder originate.
For instance, if I'm in my home directory, and delete a file within it called "temp," it will move it to ~/.Waste/home/andy/temp

So that is indeed where the file is supposed to go, but it's basing it on my PWD at the time.

I'd like to return the full path of the file name. But whatever PWD I'm in, the best I can get is "./temp"

basename and dirname are the opposite of what I need.
I tried ${FILE%} but that also returns "./temp"

I've been googling for over an hour, but getting nowhere.

Thanks, in advance.

jailbait 10-31-2008 07:08 PM

Use $PWD as a prefix to the file name.

---------------------
Steve Stites

Andy Alkaline 10-31-2008 07:28 PM

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()

nishamathew1980 11-02-2008 05:04 AM

Wow ... That's something new I learnt today. Thanks for pointing me to the article - http://andy.wordpress.com/2008/05/09...-php-realpath/

:)

Linux Archive

Andy Alkaline 11-04-2008 01:19 AM

Quote:

Originally Posted by nishamathew1980 (Post 3328956)
Wow ... That's something new I learnt today. Thanks for pointing me to the article - http://andy.wordpress.com/2008/05/09...-php-realpath/

:)

I noticed using it in a reMoval script can be a little hazardous. It won't move the symbolic link, it goes after the source file instead. Be careful!

Disillusionist 11-04-2008 01:50 AM

Code:

source="./tmp/myfile"
dest=~/.Waste/$(echo $source|sed "s@^./@$PWD@"|sed "s@^/@@")


Andy Alkaline 06-19-2009 02:29 PM

Linux console recycle bin
 
Disillusionist, thanks, but unfortunately, I don't know what your code does. Regular expressions confuse me greatly (though I'm now starting to realize how useful sed can be and that I need to learn how to use it), and I saw PWD in there; using the present working directory was something I was trying to avoid.

Here's the script so far, for anyone interested. The -u option will undo the last operation performed. This is the version currently in the subversion repo at http://sourceforge.net/projects/rmw

I won't be doing anything more with it for a few weeks or month, but if anyone has any suggestions for improvements, I'll most likely implement them at some point.

Code:

#!/bin/sh
# rmw - ReMove to Waste
# Author: Andy Alt ( https://sourceforge.net/projects/rmw/ )
# May 30, 2009
# License: GPL
# Description: ReMove to Waste, rmw, is a bash script.
# It functions as a Linux/Unix console recycle bin when
# reMoving files with rm. ReMove to Waste will move files
# to a Waste folder or "Trash can," and it will prepend
# the time and date to files when reMoving them. It keeps a
# "history" to easily copy files back to their previous location.
#
# WARNING: Use this script at your own risk.

# Change this to set the location of the rmw configuration directory
RMWCONF=${HOME}/.rmw

debug=1
# Other variables can be found in the file rmwrc (which will be created
# after this script has been run once) in your rmw config directory

displayver() {
        echo -e "\nReMove to Waste $VERSION\n"
}

displayhelp() {

echo usage: -i / interactive
echo -v / be verbose
echo -u / undo-last ReMove
echo -f / force, no prompting
 }

VERSION=0.97-svn-2009May30

if [ $# -eq 0 ]; then
        echo "No options passed"
        exit 1
fi

mvargs="-"

while getopts ":ivfuh" Option
do

case $Option in
    i    ) mvargs=$mvargs"i";;
    v    ) mvargs=$mvargs"v";;
#    v    ) verbosity=1;;
    f    ) mvargs=$mvargs"f";;
#    v    ) echo $VERSION;;
    u        ) doundo=1;;
    h        ) displayhelp;;
#    *    ) echo "Unimplemented option chosen.";;  # DEFAULT
  esac
done

shift $(($OPTIND - 1))

if [ $mvargs == "-" ]; then
        mvargs=""
fi

        if [ $doundo ]; then
                source ${RMWCONF}/undofile-last
                exit 0
        fi

#if [ $debug = 1 ]; then
       
#fi



# Create config dir if it doesn't exist
if [ ! -d ${RMWCONF} ]; then
        echo ""
        mkdir -pv ${RMWCONF}
       
        if [ ! -d ${RMWCONF} ]; then
                echo "Unable to read/write configuration directory!*"
                exit 1
        fi
fi

# Create configuration file if it doesn't exist
#
#
if [ ! -e ${RMWCONF}/rmwrc ]; then
echo ""
echo "Creating rmw configuration file ${RMWCONF}/rmwrc"
#cat > ${RMWCONF}/rmwrc << "EOF"
cat > ${RMWCONF}/rmwrc << "EOF"
# The following two lines added by rmw installation script
WASTE=${HOME}/.Waste
# After running rmw x times, disk usage of Waste directory will
# be displayed. Use 0 to disable
showdu=10
#
# Number of undo files to keep
num_undofiles=20
#
# Use verbosity even if it's not passed on the command line
# 0 to disable
verbosity=1
EOF
fi

# Read in variables from configuration file
source ${RMWCONF}/rmwrc
#


if [ ! $num_undofiles ]; then
cat >> ${RMWCONF}/rmwrc << "EOF"
# Number of undo files to keep
num_undofiles=20
EOF
num_undofiles=20
fi

if [ ! $verbosity ]; then
cat >> ${RMWCONF}/rmwrc << "EOF"
#
# Use verbosity even if it's not passed on the command line
# 0 to disable
verbosity=1
EOF
verbosity=1
fi

if [ $verbosity = 1 ]; then
        mvargs=$mvargs" -v"
fi

if [ -e ${RMWCONF}/UndoFilesCounter ]; then
       
        undofile_count=`cat ${RMWCONF}/UndoFilesCounter`
       
        else

        echo 0 > ${RMWCONF}/UndoFilesCounter
        undofile_count=1
       
        fi

if [ $undofile_count -gt $num_undofiles ]; then

        undofile_count=1

        else
       
        ((undofile_count++))

fi

echo $undofile_count > ${RMWCONF}/UndoFilesCounter

UNDO_FILE=${RMWCONF}/undofile-${undofile_count}

# BUG - This will overwrite an UNDO file even if rmw
# is being executed without filenames to ReMove
#
echo "" > $UNDO_FILE

displayver


# The mv command has a --suffix option, but I chose to
# prepend the time and date. That keeps the file extension
# intact, and thus, if desired later, more easily opened
# using a file manager
#
# date --help for more details
#
PREPENDSTR=`date +%Fh%Hm%Ms%S`

        for FILE in "${@}" ; do

        if [ -e "${FILE}" ]; then
                filecounter=1

# -h tests whether or not the file is a symlink.
# See ChangeLog (May 25, 2009) for more details.
# readlink will ReMove the source file, so if the
# file is a symlink, the readlink/abs path section
# will be skipped.

                if [ ! -h "${FILE}" ]; then

# readlink finds the absolute path of the file being reMoved.
# I use the absolute path (instead of present working directory)
# so we'll know where the file was originally located.
                ABSFILEPATH=`readlink -f "${FILE}"`
                ABSPATH=$(dirname "${ABSFILEPATH}")
                DEST=${WASTE}${ABSPATH}
                BNAME=`basename "${ABSFILEPATH}"`

# I should probably change the $DEST var to $DESTDIR
                if [ ! -d "${DEST}" ]; then
                        mkdir -vp "${DEST}"
                fi

# The three lines below write to an undo file
#
echo "if [ ! -d \"${ABSPATH}\" ]; then" >> ${UNDO_FILE}
echo "mkdir -vp \"${ABSPATH}\"" >> ${UNDO_FILE}

echo "fi" >> ${UNDO_FILE}


                        if [ ! -e "${DEST}"/"${BNAME}" ]; then
                                mv $mvargs "${ABSFILEPATH}" "${DEST}"/"${BNAME}"
                                echo mv $mvargs \""${DEST}"/"${BNAME}"\" \""${ABSFILEPATH}"\" >> $UNDO_FILE

                               
                        else
                                mv $mvargs "${ABSFILEPATH}" "${DEST}"/"${PREPENDSTR}"_"${BNAME}"
                                echo mv $mvargs \""${DEST}"/"${PREPENDSTR}"_"${BNAME}"\" \""${ABSFILEPATH}"\" >> $UNDO_FILE

                        fi

# If statement commented, I don't think it's necessary
# anymore.
#
#                if [ ! -n "$mvargs" ]; then
                        echo "ReMoved ${FILE}"
#                fi

# This is what happens to symlinks

# Removal of symlinks are not yet added to the undo file
                else

                        mkdir -pv "${WASTE}""${PWD}"
                        mv -iv "${FILE}" "${WASTE}""${PWD}"

                fi


        fi
       


        done

if [ ! -e ${RMWCONF}/timesrun ]; then
        echo 1 > ${RMWCONF}/timesrun
fi


if [ $showdu -ne 0 ];then

        timesrun=`cat ${RMWCONF}/timesrun`

        if [[ $timesrun -ge $showdu ]];
                then echo 1 > ${RMWCONF}/timesrun
                echo ""
                echo "Disk usage for Waste folder:"
                du -sh $WASTE

                elif [ $showdu -gt 0 ];then

                ((timesrun++))
                echo $timesrun > ${RMWCONF}/timesrun
        fi
fi


# Can we figure out how to empty the Waste automatically
# if directory usage exceeds x number of bytes?
#
#echo !`du -s $WASTE`!
#if [ `du -s $WASTE` gt 64000 ]; then
#        echo "Deleting Waste"
#echo "greater than 64000"
#        /bin/rm -ir $WASTE
#fi

echo ""

# If any files were ReMoved, copy the Undo file to undofile-last
# for use with the --undo-last option
# If we didn't ReMove any files, this would copy an old undo file
# to undofile-last, some of those files may not exist anymore, or we
# we wouldn't want them restored.
# Using the filecounter var to make sure that doesn't happen
#


if [[ -e $UNDO_FILE && $filecounter ]]; then
        cp -v --remove-destination $UNDO_FILE ${RMWCONF}/undofile-last
        echo ""
fi


exit 0


# end script


Disillusionist 06-19-2009 04:37 PM

Quote:

Originally Posted by Andy Alkaline (Post 3579959)
Disillusionist, thanks, but unfortunately, I don't know what your code does. Regular expressions confuse me greatly (though I'm now starting to realize how useful sed can be and that I need to learn how to use it), and I saw PWD in there; using the present working directory was something I was trying to avoid.

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.

The important part of the code I suggested, passed the value of $source through two sed statements.:
Code:

echo $source|sed "s@^./@$PWD@"|sed "s@^/@@"
The first sed statement looked was to replace any instances of ./ at the start of the variable with $PWD

The second sed statement removes the leading / character

Andy Alkaline 06-19-2009 06:00 PM

Quote:

Originally Posted by Disillusionist (Post 3580019)
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.

My only concern is that I want rmw'ed files to go to ~/.Waste/original/path. In most cases $PWD would be fine, but if I'm removing files from /tmp or ~/Documents while my pwd is /mnt/cdrom, for example, they wouldn't be quite as easy to "restore" later.

I'm still using $PWD for symlinks. I'm using 'readlink' to determine absolute paths, and it always returns the source of the symlink, which I don't want.

Disillusionist 06-20-2009 03:24 AM

The sed statement would only use PWD where the source file begins with ./

Any files that begin with ./ are by definition starting from the current working directory.

EDIT:

Your script (downloaded from sourceforge) needs to run as #!/bin/bash on my machine (although I suspect this is the same on others) as source is a shell builtin for bash, but doesn't appear to be for traditional bourne shell. -- I am using Jaunty (Ubuntu 9.04)

Andy Alkaline 06-20-2009 03:06 PM

Thanks, I made the change and issued a new file release (made some other changes too).

On Slackware, which is my primary system, /bin/sh is a symlink to /bin/bash.

ta0kira 06-20-2009 03:51 PM

Try this (where $file is e.g. ./temp):
Code:

echo "$( readlink -f "$( dirname "$file" )" )/$( basename "$file" )"
Kevin Barry

Disillusionist 06-21-2009 04:34 AM

Quote:

Originally Posted by Andy Alkaline (Post 3580795)
Thanks, I made the change and issued a new file release (made some other changes too).

On Slackware, which is my primary system, /bin/sh is a symlink to /bin/bash.

New package is missing an install.sh file

It would also be nice to see an uninstall.sh file to simplify removal.

EDIT:
As rm is linked to rmw, you need rmw to cater for all the options that rm can use, especially rm -rf

vonbiber 06-21-2009 05:51 AM

Quote:

Originally Posted by Andy Alkaline (Post 3327741)
I'm attempting to improve a bash script, ReMove to Waste. It moves files into ~/.Waste and prepends the present working directory to the destination folder under ~/.Waste.

I'd like to have it moved to the same path from where the file or folder originate.
For instance, if I'm in my home directory, and delete a file within it called "temp," it will move it to ~/.Waste/home/andy/temp

So that is indeed where the file is supposed to go, but it's basing it on my PWD at the time.

I'd like to return the full path of the file name. But whatever PWD I'm in, the best I can get is "./temp"

basename and dirname are the opposite of what I need.
I tried ${FILE%} but that also returns "./temp"

I've been googling for over an hour, but getting nowhere.

Thanks, in advance.

ok, if I understood correctly you have a bash script
(say, move2waste.sh) that is
in your $PATH, perhaps in /usr/local/bin, and when
you

move2waste.sh some_file

where some_file is in a certain directory /some/path

you want some_file to be moved to /some/path/.Waste

(provided you have the right permissions in /some/path)

I would go like that (I'll skip the permissions verifications,
the number of arguments, etc.)

#!/bin/sh

# here you loop for each argument entered,
# verifying that the file exists, etc.
# say the file to be processed is in $filename
# $filename is a basename (no preceding directories:
# you invoke the script in the directory where
# you want to move files)

CWD=$PWD
# create .Waste directory if it doesn't already exist
mkdir -p $CWD/.Waste

mv $filename $CWD/.Waste

##################################

if you want to invoke the script move2waste.sh with
arguments such as
/absolute/path/to/filename
or
relativepath/to/filename

you should, when you process these arguments, retrieve the
the part before the filename
(e.g., argument=/some/path/filename
p=${argument%/*})
then figure out if it's a relative or absolute path:
if it starts with '/' it's absolute, otherwise relative
('.', '[a-zA-Z0-9]', ...)
if it's absolute you set CWD to that: CWD=$p
if it's relative:
if it starts with './' you remove that (p=$(echo $p | sed 's?^\./??'),
if it starts with '../', you get the name of the directory above ...
then you set CWD to $CWD/$p

Andy Alkaline 06-21-2009 01:40 PM

I've been using readlink for a few months now, so I'm no longer in need of methods to use absolute paths.

Quote:

Originally Posted by Disillusionist (Post 3581145)
New package is missing an install.sh file

It would also be nice to see an uninstall.sh file to simplify removal.

EDIT:
As rm is linked to rmw, you need rmw to cater for all the options that rm can use, especially rm -rf

Thanks yet again.

I issued another release, and included the install-sh file which 'configure' requires.
I also edited it, and the configure script to change #!/bin/sh to #!/bin/bash

I added support for the -rf option. It'll be a while before I add support for all the other other options 'rm' has. I'm recovering from some pain issues which limits the amount of time I'm able to spend at the computer. Know of any good speech recog programs? :)

As for an uninstall.sh, I don't know how to do that while accounting for what users might set for a prefix install dir using 'configure'. The install-sh file is just copied from my automake directory when I create the Makefile.in.

For a workaround, I added more information to the INSTALL file about where files are being copied to. I also added an UNINSTALL file with more instructions. Additionally, I created a .deb package and an .rpm package while logged into my Kubuntu 9.04 partition and those two files are available for download on the sourceforge project page. I used checkinstall to create the packages.

Thanks for all your suggestions.


All times are GMT -5. The time now is 05:33 AM.