1

I have the following bash script, which is called trash.sh. In my script I request one parameter for from the user, simply a file name. And move the file to the Trash folder which is located in the user's home directory. If the directory doesn't exist, it simply creates one and then moves the file there. On the other hand, if the file doesn't exist, it informs the user.

#!/bin/bash

FILE=$1
FOLDER="$HOME/Trash"
ARGS=1

if [ $# -ne $ARGS ]
then
    echo "Error: You are missing an argument!"
    echo "Usage: ./trash.sh <file_name>"
else
    if [ -s $FILE ]
    then
        if [ -d $FOLDER ]
        then
            mv -v $FILE $FOLDER
        else
            mkdir $FOLDER
            mv -v $FILE $FOLDER
        fi
    else
        echo "The file you have entered does not exist!"
    fi
fi

Now, I want to extend my script in the followign ways, but I don't know how, because I am not that much experienced with bash scripting. First of all, I want to let the user enter more than one parameters, simply more then one file name, and move all the files in the Trash folder. If one or more of the files don't exist, it will inform the user which file or files don't exist. Simply, I want my script to recieve as many parameters as the user wants.

For example, if the user calls the script like this:

./trash.sh file1 file2 file3

and let's say that file2 doesn't exist I want the output to be.

file1 -> /home/user/Trash/file1
file3 -> /home/user/Trash/file3
file2 doesn't exist!

And lastly, I also want it to accept a parameter like this:

./trash *.txt

Simply, which will move all the files that end with .txt extension. If someone could help me achieve those things/extend my script, I would be glad.

1
  • 1
    You last example is identical to the previous one, as the shell (not your program) expands *.txt into a list of files. Commented Mar 19, 2013 at 18:49

1 Answer 1

2
[ $# = 0 ] && { echo "Usage: $0 file [...]" >&2; exit 1; }

FOLDER="$HOME/Trash"
mkdir -p "$FOLDER" || exit 1

for file in "$@"
do
    if [ -s "$file ]
    then mv -v "$file" "$FOLDER"
    else echo "$0: $file does not exist" >&2
    fi
done

You can detect zero arguments and issue a usage message before the loop. Using "$@" is crucial to working with filenames containing blanks, etc; ditto with using "$file" to reference the files. Using mkdir -p does not fail if the target directory already exists; it does fail if the directory can't be created or if a file with the given name exists (instead of a directory). Note that the error messages both contain $0; note that the 'file not found' message specifies the file name.

As discussed in the comments, you can simplify this in two steps:

[ $# = 0 ] && { echo "Usage: $0 file [...]" >&2; exit 1; }

FOLDER="$HOME/Trash"
mkdir -p "$FOLDER" || exit 1

for file in "$@"
do  mv -v "$file" "$FOLDER"
done

and then:

[ $# = 0 ] && { echo "Usage: $0 file [...]" >&2; exit 1; }
FOLDER="$HOME/Trash"
mkdir -p "$FOLDER" || exit 1
mv -v "$@" "$FOLDER"

Note that if you delete the makefiles in three directories, only one of them will be in the Trash.

Sign up to request clarification or add additional context in comments.

2 Comments

I think this should be simplified. Replace the entire loop with just: for file; do mv -v "$file" "$FOLDER"; done. Let mv report the error message, since the error may be something other than 'file does not exist'.
@WilliamPursell: yeah, that would be a reasonable option, especially since the errors reported by mv are not captured by the script. This script does leave empty files (size zero, because of the -s) unmoved. I was getting away from testing whether the directory exists on each iteration, for example. But then you simply do without a loop altogether: mv -v "$@" "$FOLDER", don't you?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.