6

I am working on a script that looks at a homework folder (the source files) and if the folder exists, it then looks for a destination folder. If that folder does not exist, it copies the source to the destination.

If the destination exists, it attempts to copy the file from the source to the destination and before doing so, prompt the user first so that it doesn't overwrite work already done by that user.

The output of the command must be in a specific format so I cannot use the standard output of the command as is. I must capture it and reformat it. Then take input (i.e. y/N) in a specific format.

The benefit of doing this, is that the copy command already does things that are helpful. If a file does not exist, it does the copy.

If a file, or several files already exist, it will repeatedly ask "overwrite y/n?" It is this case, that I'm trying to deal with.

I've made it as far as capturing the output of the copy command into a variable and suppressing its normal output so that I can reformat its output and echo that format back to the user.

Next, my thinking is that I need to kill (or otherwise stop the command somehow), then print the output in the my desired format and then re-invoke the command and on the second time, I can echo the y/N prompt in my desired format and the user can then make their choice. Despite searching, I have not been able to figure out/understand how to kill or otherwise stop the command once it is invoked. I've tried kill and various attempts at using SIGINT. Either I just don't understand how to use these, or they are not the right choice. When I try to use them, I get syntax error.

Here is my code:

#!/bin/bash

USAGE="Usage: ./script2.sh [hw-name]"
EINVALID="Invalid homework: $1"
SOURCEDIRECTORY="$PUBLIC/homework/$1"
HOMEWORKDIRECTORY="$HOME/homework/$1"
COPY="$SOURCEDIRECTORY/*.*"

if [ -z "$1" ]; then
    echo $USAGE
    exit
fi

if [ ! -d "$SOURCEDIRECTORY" ]; then
    echo $EINVALID
    exit
fi

if [ ! -d "$HOMEWORKDIRECTORY" ]; then
    echo "making homework1"
    mkdir -p $HOMEWORKDIRECTORY

copyOutput2="$(eval cp -ir $COPY $HOMEWORKDIRECTORY 2>&1 &stop this
 process somehow)"
echo $copyOutput2 #temporary output for testing
  • 2
    So you basically want to check if $HOMEWORKDIRECTORY/$COPY exists ? Why not simply [ -f $HOMEWORKDIRECTORY/$COPY ] before running cp? – Sergiy Kolodyazhnyy Jun 2 '18 at 22:38
  • 1
    *.* is more of a DOS/Windows convention. Generally in Linux you can just use *. – WinEunuuchs2Unix Jun 2 '18 at 23:00
  • Well, the source folder may contain any number of files. I want to copy each file but before copying, I want to test whether the same file name exists in the destination and if it does, then prompt the user (y/N) in a custom format before doing the copy. If the user types 'y' to ok a copy, then prompt again if there is another source file that has a duplicate name in the destination. Keep doing that, until there are no more duplicate names. cp does all this already, so it's beneficial to use it, but I need to customize its message to the user. – user836747 Jun 2 '18 at 23:55
4

If one really really really needs to have custom cp with custom message, then recompiling the program from source is the way to go, but a bit more sensible approach would be to write out your own message via printf preferably, instead of trying to intercept cp's output, and handle user choices via select dialog. Additionally, if you're going to output error messages, they should go to stderr stream. Finally, *.* is unnecessary and you can just use * glob instead.

Below is the script with a couple edits. Note that you need to uncomment #cp "$item" "$HOMEWORKDIRECTORY" line for the actual copying to occur. For testing purposes replace cp with echo first.

#!/bin/bash

USAGE="Usage: ./script2.sh [hw-name]"
EINVALID="Invalid homework: $1"
SOURCEDIRECTORY="$PUBLIC/homework/$1"
HOMEWORKDIRECTORY="$HOME/homework/$1"
#COPY="$SOURCEDIRECTORY/*.*"

if [ -z "$1" ]; then
    echo "$USAGE" > /dev/stderr
    exit 1
fi

if [ ! -d "$SOURCEDIRECTORY" ]; then
    echo "$EINVALID" > /dev/stderr
    exit 2
fi

if [ ! -d "$HOMEWORKDIRECTORY" ]; then
    echo "making homework1"
    mkdir -p $HOMEWORKDIRECTORY

for item in "$SOURCEDIRECTORY"/*; do
    skip=true
    if [ -f "$HOMEWORKDIRECTORY"/"${item##*/}" ]; then
        printf "%s already exists in %s.\n" "$item" "$HOMEWORKDIRECTORY"

        select choice in  "overwrite" "skip"; do
            case "$choice" in 
                "overwrite")  echo "Overwriting."  
                              break;;
                "skip") skip=true; break;;
            esac
        done
    fi

    if [ "$skip" = "true" ]; then
        continue
    fi
    echo cp "$item" "$HOMEWORKDIRECTORY"

done
  • When I try to run the script, it just returns the command line and no files are copied, no prompt given even if duplicate file exists. – user836747 Jun 3 '18 at 2:15
  • @user836747 Ah, yes, I forgot to mention that you need to uncomment #cp "$item" "$HOMEWORKDIRECTORY" ; for copying to actually happen. Just remove the # portion. Sorry, force of a habit to prevent users from accidentally overwriting precious stuff without testing first. – Sergiy Kolodyazhnyy Jun 3 '18 at 2:20
  • Thanks so much for your assistance. I tried to run it again after un-commenting the line but it still just returns to the command line with no output. Just to make sure I have the right conditions, I rechecked the source directory, and there is a file there to copy, and I checked the destination directory and there is a duplicate file there. It should give a message to confirm the copy but it just returns to command line. – user836747 Jun 3 '18 at 3:04
  • 2
    @user836747 After #!/bin/bash line add set -x. This will show diagnostic output for any shell script. See if that helps shed light on it or copy over the output to paste.ubuntu.com and provide the link. There's also shellcheck.com for checking the syntax – Sergiy Kolodyazhnyy Jun 3 '18 at 3:08
  • I tried to diagnose the issue using the output produced but I doesn't seem to tell me much so I posted the output as suggested: paste.ubuntu.com/p/PTGZYXrbZH – user836747 Jun 3 '18 at 3:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.