Help need with remove command

Hi,
Help need with remove commnad

I am using shell script where in I delete old files using the following commands:

 
rm ${DIR}/${pattern}*

We source the value of ${DIR} and ${pattern} from a config file. In some instances when the config file was missing the above parameters or say sourcing did not happen.
Then ${DIR} and ${pattern} becomes blank and the remove statement was executed as

 
rm /*

But luckily no damage was done.
I read the documentation and not really sure which one is best for me.

Help is appreciated. I want to use the safest approach as I am afraid to use rm commands.

The safest would be something like:

rm ${DIR:?'$DIR is not correctly set'}/${pattern:?'$pattern is not correctly set'}*

assuming that something else hasn't been done in your script that needs to be undone if the script dies at this point.

Thank you sir!!

---------- Post updated at 12:58 PM ---------- Previous update was at 12:27 PM ----------

I am planning to use the below code for removing files. I want to echo after all files are deleted. The order in which I delete files or all at onces does not matter.

Please let me know if there is a better way to do this.

Also I would like a safe approach in case the parameter values are blank then it should not wipe out the root directory.

 
    if `rm ${INPUTDIR:?'$INPUTDIR is not correctly set'}/${PATTERNA:?'$PATTERNA is not correctly set'}*`; then
        if `rm ${INPUTDIR:?'$INPUTDIR is not correctly set'}/${PATTERNB:?'$PATTERNB is not correctly set'}*`; then
            if `rm ${TEMPDIR:?'$TEMPDIR is not correctly set'}/${PATTERNB:?'$PATTERNB is not correctly set'}*`; then
                if `rm ${CONTROLDIR:?'$CONTROLDIR is not correctly set'}/${PATTERNB:?'$PATTERNB is not correctly set'}*.cmd`; then
                    echoen "All Files Deleted Successfully!!"
                fi
            fi
        fi
    fi  

This is overkill. You only need to use ${x:?'error msg'} once for each different $x (the first time it is referenced). And, you won't be able to list the filenames after they have been removed. And, I've never seen an echoen command.

You could try something like the following to list the files to be removed and then remove them. Don't try this if any of your filenames could contain whitespace characters! If there is a chance that any filename you're trying to remove will contain one or more whitespace characters, you need to use more complicated code.

    echo 'Preparing to remove the following files:'
    ec=1
    printf "\t%s\n" ${INPUTDIR:?'$INPUTDIR is not correctly set'}/${PATTERNA:?'$PATTERNA is not correctly set'}*
    if $(rm $INPUTDIR/$PATTERNA*); then
        printf "\t%s\n" $INPUTDIR/${PATTERNB:?'$PATTERNB is not correctly set'}*
        if $(rm $INPUTDIR/$PATTERNB*); then
            printf "\t%s\n" ${TEMPDIR:?'$TEMPDIR is not correctly set'}/$PATTERNB*
            if $(rm $TEMPDIR/$PATTERNB*); then
                printf "\t%s\n" ${CONTROLDIR:?'$CONTROLDIR is not correctly set'}/$PATTERNB*.cmd
                if $(rm $CONTROLDIR/$PATTERNB*.cmd); then
                    echo 'All Files Deleted Successfully!!'
                    ec=0
                fi
            fi
        fi
    fi
    if [ $ec -ne 0 ]; then
        echo 'Some Files Were Not Deleted!!'
    fi  

Note, this code has not been tested. I strongly suggest changing the rms in this script to echos until you verify that it will do what you're trying to do.

1 Like

Thanks I was not aware that

printf pattern*

and

echo pattern* 

will list files.

I thought

ls pattern*

was only command to list files. Thanks for the information.

When I just do

 
printf pattern*

It lists only one file and then the command prompt also comes on same line.

Whereas when I do

 
echo pattern*

It list all files and command prompt comes on next line.

Could you please let me know the following:

  1. When should we use
printf or echo

command instead of ls command.
2. Why the printf command I showed above list only one file. Where as

 
printf "\t%s\n" pattern*

list all files.
3. I am not expecting any blank space in the file name that needs to be removed but incase blank space is part of the file name. Will it just not delete that file or will it mess up the server files in root directory or any other directories.

I appreciate all your help and explaination.

Note that in all of these cases, the shell (not echo, ls, or printf) is expanding the pattern to produce a list of files. Which command you should use to process that list of files depends on what you want to do with the files in that list.

Note that there are at least three different versions of echo: AT&T's UNIX System V echo, University of California's Berkeley Software Distributions's (BSD's) echo, and the Linux GNU echo each of which have different options and each of which handle backslash characters in operands differently. If you want to write portable code, never use echo if the first character of the first operand might be a minus sign character or if any character in any operand might be a backslash character. (And you can't use -- as a first operand to skip over options and treat them as operands because some versions of echo will print the -- instead of ignoring it.) Use ls if some of the files given to it might be directories and you want ls to also list the files in the directories named by that operand, but note that the format of the output of ls (when no options are specified and the 1st operand does not begin with a minus-sign character) may differ if its standard output is directed to a terminal than if its standard output is directed to a pipe or a regular file. Use printf (with a first operand that specifies the format you want used to display any remaining operands) if you want to specify the output format and want the output to be portable to any operating system.

The first operand to printf is always interpreted as a format string to control the display of any remaining operands. If the first operand does not contain any percent-sign characters, remaining operands will be ignored.

When the first operand is "\t%s\n" or '\t%s\n' , each remaining operand will be printed as a string (%s) following a tab character (\t) and followed by a newline character (\n). If the first operand was '\t%s\t%s\t%s\t%s\n' , up to four following operands will be printed each with a leading tab character and with the last one followed by a newline character. (If the number of remaining operands is not an even multiple of 4, the final unmatched %s format specifiers will act as if empty strings were supplied to be printed.)

When you didn't supply a format string as a first operand to printf, the first file operand you you gave it was interpreted as a format string. If it didn't contain any percent-sign characters followed by other characters that printf could interpret as a valid format specifier, remaining operands would be ignored.

If any of your filenames contain space, tab, or newline characters; files you want to remove will not be removed, files you didn't want to remove may be removed instead, and other commands could be executed.

I hope this helps,
Don

1 Like
    echo 'Preparing to remove the following files:'
    ec=1
    printf "\t%s\n" ${INPUTDIR:?'$INPUTDIR is not correctly set'}/${PATTERNA:?'$PATTERNA is not correctly set'}*
    if $(rm $INPUTDIR/$PATTERNA*); then
        printf "\t%s\n" $INPUTDIR/${PATTERNB:?'$PATTERNB is not correctly set'}*
        if $(rm $INPUTDIR/$PATTERNB*); then
            printf "\t%s\n" ${TEMPDIR:?'$TEMPDIR is not correctly set'}/$PATTERNB*
            if $(rm $TEMPDIR/$PATTERNB*); then
                printf "\t%s\n" ${CONTROLDIR:?'$CONTROLDIR is not correctly set'}/$PATTERNB*.cmd
                if $(rm $CONTROLDIR/$PATTERNB*.cmd); then
                    echo 'All Files Deleted Successfully!!'
                    ec=0
                fi
            fi
        fi
    fi
    if [ $ec -ne 0 ]; then
        echo 'Some Files Were Not Deleted!!'
    fi  

The above code is failing when it finds no files with the specified pattern.
I used

rm -f

in that case the variable check we are doing to check if rm was successfull will not be any longer useful since

 rm -f 

will always return 0.

Is there any other way to do this ?
And also if time permits could you help me with code to delete files that could have space in their name.

You do not need to put any of your commands into $( ) here.

I don't see much point nesting your if's 5-deep here, check for something and if it fails, quit then and there! Keeps things simple.

if [ -z "$INPUTDIR" ] # -z means, if string is blank.
then
        echo "inputdir not set"
        exit 1
fi

if [ ! -d "$INPUTDIR" ] # -d means, if a directory by that name exists.
then
        echo "inputdir not a directory"
        exit 1
fi

# Set $1=inputdir/file1, $2=inputdir/file2, ...
# If it finds nothing, it will become the literal string inputdir/file*.
# Check if $1 exists, if it didn't, it found nothing.
set -- ${INPUTDIR}/${PATTERNB}*

if [ ! -e "$1" ] # -e means, file or directory by that name exists.
then
         echo "Nothing found matching $PATTERNB"
         exit 1
fi

if ! rm "$@"
then
        echo "Couldn't remove $@"
        exit 1
fi

echo "Removed $@"
exit 0