Have a delete bash script, want to make it "verbose."
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
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.
Introduction to Linux - A Hands on Guide
This guide was created as an overview of the Linux Operating System, geared toward new users as an exploration tour and getting started guide, with exercises at the end of each chapter.
For more advanced trainees it can be a desktop reference, and a collection of the base knowledge needed to proceed with system and network administration. This book contains many real life examples derived from the author's experience as a Linux system and network administrator, trainer and consultant. They hope these examples will help you to get a better understanding of the Linux system and that you feel encouraged to try out things on your own.
Click Here to receive this Complete Guide absolutely free.
Have a delete bash script, want to make it "verbose."
The script reads as follows:
Code:
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
# Clean Backup script
# For removing .bak, .backup and "~" files
# created by text editors (some of which are
# unaware they do it.)
find . -type f -name "*bak*" -exec rm -f {} \;
find . -type f -name "*.bak" -exec rm -f {} \;
find . -type f -name "*.backup" -exec rm -f {} \;
find . -type f -name "*~" -exec rm -f {} \;
echo "Done."
#if [ "$(ls *.bak 2>/dev/null)"]; then
# rm *.bak
#else
# echo "No files in this folder have the extension \".bak.\""
#fi
#if [ "$(ls *.backup 2>/dev/null)"]; then
# rm *.backup
#else
# echo "No files in this folder have the extension \".backup.\""
#fi
#if [ "$(ls *~ 2>/dev/null)"]; then
# rm *.~
#else
# echo "No files in this folder have a tilde at the end."
#fi
IFS="$SAVEIFS"
You'll notice there are lines commented out. These were my attempts to return the names of files to be deleted to stdout. When these lines were executable, one or another thing did not happen: either the names of the files, by extension, could not be found, or they were printed to stdout and not deleted.
How should I correct this errant behaviour in execution? I want to see the located files returned to stdout by name and actually deleted.
Are you certain that you want that first "find" command? It will find files that do not meet your stated goals. For example, it would find and remove "tom_baker_resume.txt".
Chops to norobo. That command works very well. I have another script, killoriginal, which writes the file names of the items it deletes, and I would like this script, named cleanback, to do the same. Where would I add the command to 'log' the files this one deletes?
Re mturns suggestion: Should *bak and *~ work to avoid the error of removing files names with those strings (?!) elsewhere, as in your example of "tom_baker.txt"? I think i tried that once and it failed to work; of course then I was using the other find commands (see original script in my OP).
Carver
Last edited by L_Carver; 12-22-2017 at 09:05 AM.
Reason: Corrected spellings.
A comment to the given answer: -print -delete prints the files to be deleted. But a deletion can fail, "permission denied" or "read-only filesystem".
Therefore it makes sense to switch the order. -delete -print prints if the deletion succeeded.
you must forget that IFS thing, do you really need it?
instead of
Code:
if [ "$(ls *.bak 2>/dev/null)"]; then
rm *.bak
else
echo "No files in this folder have the extension \".bak.\""
fi
you can simply write:
Code:
rm -f *.bak
# --- or ---
rm *.bak
#that will report if that was not found.
# --- and ---
# if you want to modify the error message:
rm *.bak 2>/dev/null || echo Error: '*.bak' was not found >&2
If you want to print filenames, just use:
Code:
echo *.bak
or if you want to check if that exists:
Code:
A=( *.bak )
if [[ "${A[0]}" == '*.bak' ]]; then
echo *.bak was not found
else
echo deleting *.bak
rm *.bak
fi
for f in *.bak
is deprecated and works only if there was no space or any other "strange" character in the filenames. Would be better to check if ${A[0]} was a real file as you suggested. Another solution would be to use the option failglob (shopt -o failglob).
for f in *.bak is not deprecated, and the globbing works well with spaces in filenames (and with other soecial characters).
Probably you mix it up with for f in $var that can be problematic because word splitting (and then globbing) happens after variable substitution.
At the time you see the filename, it no longer exists.
I wonder about the usefulness of this information
With my killoriginal script, it gives me quick confirmation that that script works. Sometimes I may want to see how many backup files my preferred text editors create (those are Pluma and Xed.).
SO how might I get this script to log the deleted files by name, like killoriginal? Or is it even possible?
Distribution: Red Hat (8.0, RHEL5,6), CentOS, SuSE (10.x, 11.x, 12.2, 13.2), Solaris (8-10), Tru64, MacOS, Raspian
Posts: 1,187
Rep:
Quote:
Originally Posted by L_Carver
Re mturns suggestion: Should *bak and *~ work to avoid the error of removing files names with those strings (?!) elsewhere, as in your example of "tom_baker.txt"? I think i tried that once and it failed to work; of course then I was using the other find commands (see original script in my OP).
Before deleting files, I tend to want to try running the "find" commands without the "-exec ..." portion. You'll see if any files are being found that you didn't expect/want to be in the list to be deleted. Especially since you're not specifying an exact path for the find command to locate files. (Would this be something you'd want to accidently run on "/", "/usr", etc?) Better to be sure than having to hope your last backup was successful.
I guess this has been rattling around in the back of my mind since I first saw it on LQ...
What if you did:
Code:
#!/bin/bash
(
find . -type f -name "*bak*" # I still see a problem w/ this pattern
find . -type f -name "*.bak"
find . -type f -name "*.backup"
find . -type f -name "*~"
) | while read FP
do
echo "Removing ${FP}..."
rm ${FP}
done
You could also eliminate the "echo" by using "rm -v". (Is there a reason you don't want to use that switch?)
You could also string the name patterns together in a single "find":
With my killoriginal script, it gives me quick confirmation that that script works. Sometimes I may want to see how many backup files my preferred text editors create (those are Pluma and Xed.).
SO how might I get this script to log the deleted files by name, like killoriginal? Or is it even possible?
Carver
Did you try the solution from MadeInGermany (post #8)?
Did you try the solution from norobro (post #2)?
What is the problem with them? What kind of log do you need? What is that your killoriginal script?
Running 4 different find commands will be relatively slow, so better to use -o as it was already mentioned. But if you have only one single directory (without subdirs) again MadeInGermany gave a good tip:
Code:
for f in *.bak *.backup *~
do
if [ -f "$f" ]
then
rm "$f" &&
echo "$f deleted"
fi
done
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.