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.