LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Have a delete bash script, want to make it "verbose." (https://www.linuxquestions.org/questions/linux-newbie-8/have-a-delete-bash-script-want-to-make-it-verbose-4175619092/)

L_Carver 12-06-2017 03:08 PM

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.

Carver.

norobro 12-06-2017 04:31 PM

Will the -print and -delete options of find not do what you want?
Code:

$ find . -type f \( -name "*bak*" -o -name "*~" \)  -print -delete

rnturn 12-11-2017 08:09 PM

Quote:

Originally Posted by L_Carver (Post 5789777)
# 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 {} \;

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".

L_Carver 12-22-2017 09:04 AM

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

MadeInGermany 12-22-2017 12:43 PM

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.

keefaz 12-22-2017 05:09 PM

At the time you see the filename, it no longer exists.
I wonder about the usefulness of this information

pan64 12-23-2017 02:32 AM

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

(not tested)

MadeInGermany 12-23-2017 03:19 AM

Quote:

if [[ "${A[0]}" == '*.bak' ]]; then
will not delete a file that is really named *.bak
You also must test if it exists.

A for loop does it correctly, and ensures that all items are files.
Code:

for f in *.bak
do
  if [ -f "$f" ]
  then
    rm "$f" &&
    echo "$f  deleted"
  fi
done


pan64 12-23-2017 04:45 AM

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

MadeInGermany 12-24-2017 09:10 AM

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.

L_Carver 12-27-2017 02:21 PM

Quote:

Originally Posted by keefaz (Post 5796608)
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?

Carver

rnturn 12-27-2017 09:54 PM

Quote:

Originally Posted by L_Carver (Post 5796434)
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.

rnturn 12-27-2017 10:13 PM

Quote:

Originally Posted by L_Carver (Post 5789777)
# 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 {} \;

[snip]

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":
Code:

find . -type f -name "*bak*" -o -name "*.bak" -o -name "*.backup" -o -name "*~"
and forego the enclosing parentheses before the pipe.

Just a couple of things you could consider.

Later...

pan64 12-28-2017 04:11 AM

Quote:

Originally Posted by L_Carver (Post 5798496)
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



All times are GMT -5. The time now is 08:30 PM.