[SOLVED] bash script - return full path and filename
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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, 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
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.
Last edited by Andy Alt; 06-19-2009 at 06:03 PM.
Reason: addendum
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)
Last edited by Disillusionist; 06-20-2009 at 04:01 AM.
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
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
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.