Home > Enterprise >  Copy files to destination and create destination if does not exist
Copy files to destination and create destination if does not exist

Time:04-19

I am writing a bash script to copy ONE or MORE THAN ONE or ALL files to a destination, and create the destination if it does not exist.

I have already gone through this solution but it does not complete my requirements.

My code (Which does not work for idk what reasons):

# copy files and make a directory if does not exist
mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    # loop over all arguments
    for file in "$@"
    do
        # if file is last argument (directory) then break loop
        if [ "$file" == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

I want all these commands to be working:

# copies "text.txt" to "testdir" (testdir may or may not exist so it must be created first)
$ mkcp test.txt ~/desktop/testdir

# copies "test1.txt" and "test2.txt" to "testdir" (conditions are same)
$ mkcp test1.txt test2.txt ~/desktop/testdir

# copies "all files" to "testdir" (conditions are same)
$ mkcp * ~/desktop/testdir

If there's any other solution that can complete my requirements, I am okay with it too.

Note: The mkcp function is stored in .zshrc.

CodePudding user response:

This is what the main changes I suggest should look like:

mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    # loop over all arguments
    for file in "$@"
    do
        # if file is last argument (directory) then break loop
        if [ "$file" == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

I'm not clear how you'd get the error message mkcp:9: = not found; to debug that, I'd need to see your modified code. OTOH, I'm not convinced that debugging that is going to be particularly constructive.

CodePudding user response:

The error is on this command

# copies "all files" to "testdir" (conditions are same)
$ mkcp * ~/desktop/testdir

You're passing a string "*" as command to a custom function, so when you send *mkcp * you're actually saying "cp -R * /path" where * is just a string, not 'all'.

You can try to do this way:

mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    
    # loop over all arguments
    for file in "$@"
    do
        if [[ "${file}" == "*" ]]; then
            LIST_FILE=$(ls $dir)
            for i in $LIST_FILE
            do
               cp $i $dir
            done
            break
        fi
        # if file is last argument (directory) then break loop
        if [ file == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

If you need to 'debug' what the script is executing, try to run the script as:

bash -x mkcp * ~/desktop/testdir

The -x will how each step of the script.

Hope it helps.

CodePudding user response:

I added this bash answer before I realized this is a zsh question. Not deleting it in hopes others find it useful.


You can take a sublist of the positional arguments using the ${var:offset:length} expansion. See Shell Parameter Expansion in the manual.

Perhaps this:

mkcp() {
    local dir="${@: -1}"

    mkdir -p "$dir"

    for file in "${@:0:$#}"     # all but last
    do
        cp -vR "$file" "$dir"
    done
}

In fact, it can be simpler, assuming you have GNU cp with the -t option:

mkcp() {
    local dir="${@: -1}"
    mkdir -p "$dir"
    cp -t "$dir" -vR "${@:0:$#}"
}

I added cp's -v option for extra verbosity, so you can see what files are being copied.

  • Related