'Copy files to destination and create destination if does not exist
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.
Solution 1:[1]
You assume that the last argument must be a directory, and if no such directory exists, it should be created. In zsh, I would do it like this:
mkcp() {
local destdir=$@[-1]
if [[ -f $destdir ]]
then
echo Missing destination directory 2>&1
return 1
else
mkdir -p $destdir
if [[ -d $destdir ]]
then
cp "$@"
else
echo Can not create $destdir
return 1
fi
fi
}
The problem is not the copying (the plain cp command can do it and no loop is needed), so the focus here is on error checking.
Note that with my approach, switches can be passed implicitly to cp, for instance
mkcp -r foo bar baz
copies recursively the subdirectories too, and
mkcp -rv foo bar baz
is in addition printing the names of the files which are copied.
Solution 2:[2]
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.
Solution 3:[3]
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.
Solution 4:[4]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | user1934428 |
| Solution 2 | glenn jackman |
| Solution 3 | Jonathan Leffler |
| Solution 4 | DharmanBot |
