Bash renaming from path variable - linux

I'm doing a "Recycle bin" type script, I have it all done however if a file already exists where I try to restore the file I want it to let the user choose a new name for the file to be restored as, I have the full path the file was deleted from in variable $F1 I just dont know how I go about changing the file name here
#!/bin/bash
TRASHCAN ="/home/alihassan/Desktop/Trashcan"
cd $TRASHCAN
F1=$( grep "$1" storage.txt )
if [ -f $F1 ]
then echo "File already exists at the restore location, please enter a new filename"
read ANS
mv "home/alihassan/Desktop/Trashcan/$1" "$F1/$ #ISSUE IS HERE
else
mv "/home/alihassan/Desktop/Trashcan/$1" "$F1"
fi

On the face of it, you might be after:
mv "$TRASHCAN/$1" $(dirname "$F1")/"$ANS"
This preserves the original path from $F1 for all except the last component, and then uses the answer in place of the last component.

Use parameter expansion to find the original directory:
read ANS
mv "home/alihassan/Desktop/Trashcan/$1" "${F1%/*}/$ANS"
As Jonathan commented about, there is nothing stopping you from "restoring" a file on top of an existing file, overwriting it. You might want to test for the existence of the restore location before performing that mv, eg:
while read ANS; do
if [ ! -f "${F1%/*}/$ANS" ]; then
mv "home/alihassan/Desktop/Trashcan/$1" "${F1%/*}/$ANS"
break
else
echo "File already exists - please choose another name"
fi
done

Related

Bash script to iterate contents of directory moving only the files not currently open by other process

I have people uploading files to a directory on my Ubuntu Server.
I need to move those files to the final location (another directory) only when I know these files are fully uploaded.
Here's my script so far:
#!/bin/bash
cd /var/uploaded_by_users
for filename in *; do
lsof $filename
if [ -z $? ]; then
# file has been closed, move it
else
echo "*** File is open. Skipping..."
fi
done
cd -
However it's not working as it says some files are open when that's not true. I supposed $? would have 0 if the file was closed and 1 if it wasn't but I think that's wrong.
I'm not linux expert so I'm looking to know how to implement this simple script that will run on a cron job every 1 minute.
[ -z $? ] checks if $? is of zero length or not. Since $? will never be a null string, your check will always fail and result in else part being executed.
You need to test for numeric zero, as below:
lsof "$filename" >/dev/null; lsof_status=$?
if [ "$lsof_status" -eq 0 ]; then
# file is open, skipping
else
# move it
fi
Or more simply (as Benjamin pointed out):
if lsof "$filename" >/dev/null; then
# file is open, skip
else
# move it
fi
Using negation, we can shorten the if statement (as dimo414 pointed out):
if ! lsof "$filename" >/dev/null; then
# move it
fi
You can shorten it even further, using &&:
for filename in *; do
lsof "$filename" >/dev/null && continue # skip if the file is open
# move the file
done
You may not need to worry about when the write is complete, if you are moving the file to a different location in the same file system. As long as the client is using the same file descriptor to write to the file, you can simply create a new hard link for the upload file, then remove the original link. The client's file descriptor won't be affected by one of the links being removed.
cd /var/uploaded_by_users
for f in *; do
ln "$f" /somewhere/else/"$f"
rm "$f"
done

Moving files in different folder changing the names

I am trying to write a script to move some file in a common folder.
Basically I have n folders and in each of them there is a file called xmu.dat; I want to copy these files in a different folder changing its names.
This is the code I came up with (I have never written a script before...), but I get some errors:
echo "Folders found:"
for folder in */
do
echo "$folder"
name = ${folder//[\/]/}
cp ./"$folder"/xmu.dat ./OutputFiles/name
done
As fedorqui said, the issue with your code is the presence of whitespaces around the '='.
If you want to check if a file exists, you can use the '-f' option, as:
if [ -f "$file" ]
then
echo "$file found."
else
echo "$file not found."
fi

Moving multiple files in directory that have duplicate file names [duplicate]

This question already has answers here:
Moving multiple files in directory that might have duplicate file names
(2 answers)
Closed 9 years ago.
can anyone help me with this?
I am trying to copy images from my USB to an archive on my computer, I have decided to make a BASH script to make this job easier. I want to copy files(ie IMG_0101.JPG) and if there is already a file with that name in the archive (Which there will be as I wipe my camera everytime I use it) the file should be named IMG_0101.JPG.JPG so that I don't lose the file.
#!/bin/bash
if [ $# -eq 0 ]
then
echo "Usage: $0 image_path archive_path"
exit 999
fi
if [ -d "$1" ] #Checks if archive directory exists
then
echo Image Source directory FOUND
else
echo ERROR: Image Source directory has NOT BEEN FOUND
fi
if [ -d "$2" ]
then
echo Photo Archive FOUND
else
echo Creating directory
mkdir "$2"
fi
if [ find $1 -name "IMG_[0-9][0-9][0-9][0-9].JPG" ] #added this in to be more specific 1/4
then #2/4
for file in "$1"/*
do
dupefile= "$2"/"$file"
while [ -e "$newfile" ];
do
newfile=$newfile.JPG
done
mv "$file" "$newfile"
done
else #3/4
#do nothing
fi #4/4 took all the /4 out, but it's saying theres no such file or directory, even though I've tested it and it says there is.
unexpected token fi is the error I'm getting but the if statement needs to be in there so the specific files i need, are getting moved.
You cannot have an empty else. Take out the else keyword if you don't have an else part.
Also, you should get rid of the superfluous find. Just loop over the files you actually want instead.
for file in "$1"/IMG_[0-9][0-9][0-9][0-9].JPG
do
newfile= "$2"/"$file"
while [ -e "$newfile" ];
do
newfile=$newfile.JPG
done
mv "$file" "$newfile"
done
done
(This also addresses the dupefile vs newfile error.)

Remove in linux

hey so I have some code for the question bellow but I am stuck its not working and I don't really know what I am doing.
This script should remove the contents of the dustbin directory.
If the -a option is used the script should remove ALL files from the dustbin.
Otherwise, the script should display the filenames in the dustbin one by one and ask the user for confirmation that they should be deleted
#!/bin/sh
echo " The files in the dustbin are : "
ls ~/TAM/dustbin
read -p " Please enter -a to delete all files else you will be prompted to delete one by one : " filename
read ans
if ["filename" == "-a"]
cat ~/TAM/dustbin
rm -rf*
else
ls > ~/TAM/dustbin
for line in `cat ~/TAM/dustbin`
do
echo "Do you want to delete this file" $line
echo "Y/N"
read ans
case "ans" in
Y) rm $line ;;
N) "" ;;
esac
EDITED VERSION
if test ! -f ~/TAM/dustbin/*
then
echo "this directory is empty"
else
for resfile in ~/TAM/dustbin/*
do
if test -f $resfile ; then
echo "Do you want to delete $resfile"
echo "Y/N"
read ans
if test $ans = Y ; then
rm $resfile
echo "File $resfile was deleted"
fi
fi
done
fi
this works however Now I get one of 2 errors either
line 4 requires a binary operator or line 4: to many arguments
I see one obvious mistake:
rm -rf*
when it should be
rm -rf *
to be asked about every file deletion - add -i key
rm -rfi *
Many problems here:
A space missing before the * in rm. The space is needed so the shell can recognize the wildcard and expand it.
Do you really want to remove all the files in the current directory? If not, specify the path rm -rf /path/to/files/* or cd into the directory, preferably with cd /path/to/files || exit 1.
I do not understand the logic of the script. You show a dustbin, but if the user gives -a, you overwrite it with all the non-hidden files (ls > dustbin). Is that what you want?
First of all, case "ans" of just matches a string "ans" to other strings, which is obviously false, you need case $ans of to get the value of variable ans. if ["filename" == "-a"] is also comparison between two strings, which is always false. The first parameter of a script can be accessed as $1 (the second as $2 and so on).
Please read man 1 sh to get the basics of shell programming (all of the above notes can be found there).

Linux file deletion error

Every time I run this code I get the error File or directory doesn't exist. Why?
read -p "Enter the filename/path of the file you wish to delete : " filename
echo "Do you want to delete this file"
echo "Y/N"
read ans
case "$ans" in
Y) "`readlink -f $filename`" >>~/TAM/store & mv $filename ~/TAM/dustbin
echo "File moved" ;;
N) "File Not deleted" ;;
esac
When I enter the file name/directory exactly and triple check its right I still get this error, but the readlink part works.
Paraphrasing/summarizing/extending my answer for a similar question:
I doubt you really meant to use & instead of && in your script.
"File Not deleted" is not a valid command on any Linux system that I have used. Perhaps you are missing an echo there?
You have to fix your variable quotation. If the filename variable contains whitespace, then $filename is expanded by the shell into more than one arguments. You need to enclose it into double quotes:
mv "$filename" ~/TAM/dustbin
I do not see your script creating the ~/TAM/ directory anywhere...
You are missing an echo and one &&.
Use echo "`command`" to pipe the result string of commands. Alternatively, you may directly use the command without backticks and quotes, (not storing the result in a string), in which case you do not need an echo because the command will pipe its result to the next command.
The single & will run the preceding command in the background (async.). To check for return values and conditionally execute you need && and ||.
Here is a complete solution/example (incl. some more logging):
# modified example not messing the $HOME dir.
# should be save to run in a separate dir
touch testfile #create file for testing
read -p "Enter the filename/path of the file you wish to delete : " filename
echo "Do you want to delete this file: $filename"
echo "Y/N"
read ans
touch movedfiles #create a file to store the moved files
[ -d _trash ] || mkdir _trash #create a dustbin if not already there
case "$ans" in
Y) readlink -f "$filename" >> movedfiles && echo "File name stored" &&
mv "$filename" _trash && echo "File moved" ;;
N) echo "File Not deleted" ;;
esac
cat movedfiles #display all moved files

Resources